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