1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 #ifdef LTC_PBES
6
s_pkcs_5_alg1_wrap(const unsigned char * password,unsigned long password_len,const unsigned char * salt,unsigned long salt_len,int iteration_count,int hash_idx,unsigned char * out,unsigned long * outlen)7 static int s_pkcs_5_alg1_wrap(const unsigned char *password, unsigned long password_len,
8 const unsigned char *salt, unsigned long salt_len,
9 int iteration_count, int hash_idx,
10 unsigned char *out, unsigned long *outlen)
11 {
12 LTC_UNUSED_PARAM(salt_len);
13 return pkcs_5_alg1(password, password_len, salt, iteration_count, hash_idx, out, outlen);
14 }
15
s_pkcs_12_wrap(const unsigned char * password,unsigned long password_len,const unsigned char * salt,unsigned long salt_len,int iteration_count,int hash_idx,unsigned char * out,unsigned long * outlen)16 static int s_pkcs_12_wrap(const unsigned char *password, unsigned long password_len,
17 const unsigned char *salt, unsigned long salt_len,
18 int iteration_count, int hash_idx,
19 unsigned char *out, unsigned long *outlen)
20 {
21 int err;
22 /* convert password to unicode/utf16-be */
23 unsigned long pwlen = password_len * 2;
24 unsigned char* pw;
25 if (*outlen < 32) return CRYPT_INVALID_ARG;
26 pw = XMALLOC(pwlen + 2);
27 if (pw == NULL) return CRYPT_MEM;
28 if ((err = pkcs12_utf8_to_utf16(password, password_len, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR;
29 pw[pwlen++] = 0;
30 pw[pwlen++] = 0;
31 /* derive KEY */
32 if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR;
33 /* derive IV */
34 if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR;
35
36 *outlen = 32;
37 LBL_ERROR:
38 zeromem(pw, pwlen);
39 XFREE(pw);
40 return err;
41 }
42
43 static const pbes_properties s_pbes1_types[] = {
44 { s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 },
45 { s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 },
46 { s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 },
47 { s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 },
48 { s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 },
49 { s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 },
50 { s_pkcs_12_wrap, "sha1", "3des", 24, 8 },
51 };
52
53 typedef struct {
54 const pbes_properties *data;
55 const char *oid;
56 } oid_to_pbes;
57
58 static const oid_to_pbes s_pbes1_list[] = {
59 { &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
60 { &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
61 { &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
62 { &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
63 { &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
64 { &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
65 { &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
66 { 0 },
67 };
68
s_pbes1_from_oid(const ltc_asn1_list * oid,pbes_properties * res)69 static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res)
70 {
71 unsigned int i;
72 for (i = 0; s_pbes1_list[i].data != NULL; ++i) {
73 if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) {
74 if (res != NULL) *res = *s_pbes1_list[i].data;
75 return CRYPT_OK;
76 }
77 }
78 return CRYPT_INVALID_ARG;
79 }
80
81 /**
82 Extract PBES1 parameters
83
84 @param s The start of the sequence with potential PBES1 parameters
85 @param res Pointer to where the extracted parameters should be stored
86 @return CRYPT_OK on success
87 */
pbes1_extract(const ltc_asn1_list * s,pbes_arg * res)88 int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res)
89 {
90 int err;
91
92 LTC_ARGCHK(s != NULL);
93 LTC_ARGCHK(res != NULL);
94
95 if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err;
96
97 if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
98 !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) ||
99 !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) {
100 return CRYPT_INVALID_PACKET;
101 }
102 /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
103 * 0:d=0 hl=4 l= 329 cons: SEQUENCE
104 * 4:d=1 hl=2 l= 27 cons: SEQUENCE
105 * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s)
106 * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
107 * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
108 * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
109 * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
110 */
111 res->salt = s->next->child;
112 res->iterations = mp_get_int(s->next->child->next->data);
113
114 return CRYPT_OK;
115 }
116
117 #endif
118