1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 #ifdef LTC_PKCS_8
6
7 /**
8 PKCS#8 decrypt if necessary & flexi-decode
9
10 @param in Pointer to the ASN.1 encoded input data
11 @param inlen Length of the input data
12 @param pwd Pointer to the password that was used when encrypting
13 @param pwdlen Length of the password
14 @param decoded_list Pointer to a pointer for the flexi-decoded list
15 @return CRYPT_OK on success
16 */
pkcs8_decode_flexi(const unsigned char * in,unsigned long inlen,const void * pwd,unsigned long pwdlen,ltc_asn1_list ** decoded_list)17 int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
18 const void *pwd, unsigned long pwdlen,
19 ltc_asn1_list **decoded_list)
20 {
21 unsigned long len = inlen;
22 unsigned long dec_size;
23 unsigned char *dec_data = NULL;
24 ltc_asn1_list *l = NULL;
25 int err;
26
27 LTC_ARGCHK(in != NULL);
28 LTC_ARGCHK(decoded_list != NULL);
29
30 *decoded_list = NULL;
31 if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
32 /* the following "if" detects whether it is encrypted or not */
33 /* PKCS8 Setup
34 * 0:d=0 hl=4 l= 380 cons: SEQUENCE
35 * 4:d=1 hl=2 l= 78 cons: SEQUENCE
36 * 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid)
37 * 17:d=2 hl=2 l= 65 cons: SEQUENCE
38 * Stuff in between is dependent on whether it's PBES1 or PBES2
39 * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
40 */
41 if (l->type == LTC_ASN1_SEQUENCE &&
42 LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) &&
43 LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) &&
44 LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) &&
45 LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) {
46 ltc_asn1_list *lalgoid = l->child->child;
47 pbes_arg pbes;
48
49 XMEMSET(&pbes, 0, sizeof(pbes));
50
51 if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) {
52 /* Successfully extracted PBES1 parameters */
53 } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) {
54 /* Successfully extracted PBES2 parameters */
55 } else {
56 /* unsupported encryption */
57 err = CRYPT_INVALID_PACKET;
58 goto LBL_DONE;
59 }
60
61 pbes.enc_data = l->child->next;
62 pbes.pwd = pwd;
63 pbes.pwdlen = pwdlen;
64
65 dec_size = pbes.enc_data->size;
66 if ((dec_data = XMALLOC(dec_size)) == NULL) {
67 err = CRYPT_MEM;
68 goto LBL_DONE;
69 }
70
71 if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE;
72
73 der_free_sequence_flexi(l);
74 l = NULL;
75 err = der_decode_sequence_flexi(dec_data, &dec_size, &l);
76 if (err != CRYPT_OK) goto LBL_DONE;
77 *decoded_list = l;
78 }
79 else {
80 /* not encrypted */
81 err = CRYPT_OK;
82 *decoded_list = l;
83 }
84 /* Set l to NULL so it won't be free'd */
85 l = NULL;
86 }
87
88 LBL_DONE:
89 if (l) der_free_sequence_flexi(l);
90 if (dec_data) {
91 zeromem(dec_data, dec_size);
92 XFREE(dec_data);
93 }
94 return err;
95 }
96
97 #endif
98