1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 #include "tomcrypt_private.h"
11 
12 #ifdef LTC_PBES
13 
14 static const char * const _oid_pbes2 =  "1.2.840.113549.1.5.13";
15 static const char * const _oid_pbkdf2 = "1.2.840.113549.1.5.12";
16 
17 typedef struct {
18    const char *oid;
19    const char *id;
20 } oid_id_st;
21 
22 static const oid_id_st _hmac_oid_names[] = {
23    { "1.2.840.113549.2.7",  "sha1" },
24    { "1.2.840.113549.2.8",  "sha224" },
25    { "1.2.840.113549.2.9",  "sha256" },
26    { "1.2.840.113549.2.10", "sha384" },
27    { "1.2.840.113549.2.11", "sha512" },
28    { "1.2.840.113549.2.12", "sha512-224" },
29    { "1.2.840.113549.2.13", "sha512-256" },
30 };
31 
32 static const pbes_properties _pbes2_default_types[] = {
33    { pkcs_5_alg2, "sha1",   "des",   8, 0 },
34    { pkcs_5_alg2, "sha1",   "rc2",   4, 0 },
35    { pkcs_5_alg2, "sha1",   "3des", 24, 0 },
36    { pkcs_5_alg2, "sha1",   "aes",  16, 0 },
37    { pkcs_5_alg2, "sha1",   "aes",  24, 0 },
38    { pkcs_5_alg2, "sha1",   "aes",  32, 0 },
39 };
40 
41 typedef struct {
42    const pbes_properties *data;
43    const char* oid;
44 } oid_to_pbes;
45 
46 static const oid_to_pbes _pbes2_list[] = {
47    { &_pbes2_default_types[0], "1.3.14.3.2.7"            },  /* http://www.oid-info.com/get/1.3.14.3.2.7            desCBC */
48    { &_pbes2_default_types[1], "1.2.840.113549.3.2"      },  /* http://www.oid-info.com/get/1.2.840.113549.3.2      rc2CBC */
49    { &_pbes2_default_types[2], "1.2.840.113549.3.7"      },  /* http://www.oid-info.com/get/1.2.840.113549.3.7      des-EDE3-CBC */
50    { &_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2"  },  /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2  aes128-CBC */
51    { &_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" },  /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */
52    { &_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" },  /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */
53 };
54 
_pbes2_from_oid(const ltc_asn1_list * cipher_oid,const ltc_asn1_list * hmac_oid,pbes_properties * res)55 static int _pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res)
56 {
57    unsigned int i;
58    for (i = 0; i < sizeof(_pbes2_list)/sizeof(_pbes2_list[0]); ++i) {
59       if (pk_oid_cmp_with_asn1(_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) {
60          *res = *_pbes2_list[i].data;
61          break;
62       }
63    }
64    if (res->c == NULL) return CRYPT_INVALID_CIPHER;
65    if (hmac_oid != NULL) {
66       for (i = 0; i < sizeof(_hmac_oid_names)/sizeof(_hmac_oid_names[0]); ++i) {
67          if (pk_oid_cmp_with_asn1(_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) {
68             res->h = _hmac_oid_names[i].id;
69             return CRYPT_OK;
70          }
71       }
72       return CRYPT_INVALID_HASH;
73    }
74    return CRYPT_OK;
75 }
76 
77 
78 /**
79    Extract PBES2 parameters
80 
81    @param s     The start of the sequence with potential PBES2 parameters
82    @param res   Pointer to where the extracted parameters should be stored
83    @return CRYPT_OK on success
84 */
pbes2_extract(const ltc_asn1_list * s,pbes_arg * res)85 int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res)
86 {
87    unsigned long klen;
88    ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac;
89    int err;
90 
91    LTC_ARGCHK(s   != NULL);
92    LTC_ARGCHK(res != NULL);
93 
94    if ((err = pk_oid_cmp_with_asn1(_oid_pbes2, s)) != CRYPT_OK) return err;
95 
96    if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
97        !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) ||
98        !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) ||
99        !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) ||
100        !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) ||
101        !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
102       return CRYPT_INVALID_PACKET;
103    }
104    /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
105     *  0:d=0  hl=4 l= 380 cons: SEQUENCE
106     *  4:d=1  hl=2 l=  78 cons:   SEQUENCE
107     *  6:d=2  hl=2 l=   9 prim:     OBJECT             :PBES2 (== 1.2.840.113549.1.5.13) (== *s)
108     * 17:d=2  hl=2 l=  65 cons:     SEQUENCE
109     * 19:d=3  hl=2 l=  41 cons:       SEQUENCE
110     * 21:d=4  hl=2 l=   9 prim:         OBJECT         :PBKDF2 (== *lkdf)
111     * 32:d=4  hl=2 l=  28 cons:         SEQUENCE
112     * 34:d=5  hl=2 l=   8 prim:           OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt)
113     * 44:d=5  hl=2 l=   2 prim:           INTEGER      :0800 (== res->iterations, *liter)
114     * 48:d=5  hl=2 l=  12 cons:           SEQUENCE     (== *loptseq   - this sequence is optional, may be missing)
115     * 50:d=6  hl=2 l=   8 prim:             OBJECT     :hmacWithSHA256 (== *lhmac)
116     * 60:d=6  hl=2 l=   0 prim:             NULL
117     * 62:d=3  hl=2 l=  20 cons:       SEQUENCE
118     * 64:d=4  hl=2 l=   8 prim:         OBJECT         :des-ede3-cbc (== *lenc)
119     * 74:d=4  hl=2 l=   8 prim:         OCTET STRING   [HEX DUMP]:B1404C4688DC9A5A
120     * 84:d=1  hl=4 l= 296 prim:   OCTET STRING         :bytes (== encrypted data)
121     */
122    lkdf = s->next->child->child;
123    lenc = s->next->child->next->child;
124 
125    if ((err = pk_oid_cmp_with_asn1(_oid_pbkdf2, lkdf)) != CRYPT_OK) return err;
126 
127    if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) ||
128        !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) ||
129        !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) {
130       return CRYPT_INVALID_PACKET;
131    }
132 
133    liter = lkdf->next->child->next;
134    loptseq = liter->next;
135    res->salt = lkdf->next->child;
136    res->iterations = mp_get_int(liter->data);
137 
138    /* There's an optional INTEGER keyLength after the iterations, skip that if it's there.
139     * c.f. RFC 2898 A.2 PBKDF2 */
140    if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) {
141       loptseq = loptseq->next;
142    }
143 
144    /* this sequence is optional */
145    lhmac = NULL;
146    if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) &&
147        LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
148       lhmac = loptseq->child;
149    }
150    if ((err = _pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err;
151 
152    if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) {
153       /* 'NON-RC2'-CBC */
154       res->iv = lenc->next;
155    } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) {
156       /* RC2-CBC is a bit special ...
157        *
158        * RC2-CBC-Parameter ::= SEQUENCE {
159        *     rc2ParameterVersion INTEGER OPTIONAL,
160        *     iv OCTET STRING (SIZE(8)) }
161        */
162       if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) &&
163           LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) {
164          klen = mp_get_int(lenc->next->child->data);
165          res->iv   = lenc->next->child->next;
166          /*
167           * Effective Key Bits         Encoding
168           *         40                    160
169           *         64                    120
170           *        128                     58
171           *       b >= 256                  b
172           */
173          switch (klen) {
174             case 160:
175                res->key_bits = 40;
176                break;
177             case 120:
178                res->key_bits = 64;
179                break;
180             case 58:
181                res->key_bits = 128;
182                break;
183             default:
184                /* We don't handle undefined Key Bits */
185                if (klen < 256) return CRYPT_INVALID_KEYSIZE;
186 
187                res->key_bits = klen;
188                break;
189          }
190       } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) {
191          res->iv   = lenc->next->child;
192          /*
193           * If the rc2ParameterVersion field is omitted, the "effective key bits"
194           * defaults to 32.
195           */
196          res->key_bits = 32;
197       } else {
198          return CRYPT_INVALID_PACKET;
199       }
200    }
201 
202    return CRYPT_OK;
203 }
204 
205 #endif
206 
207 /* ref:         $Format:%D$ */
208 /* git commit:  $Format:%H$ */
209 /* commit time: $Format:%ai$ */
210