1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file rsa_import_pkcs8.c
7   Import a PKCS RSA key
8 */
9 
10 #ifdef LTC_MRSA
11 
12 /* Public-Key Cryptography Standards (PKCS) #8:
13  * Private-Key Information Syntax Specification Version 1.2
14  * https://tools.ietf.org/html/rfc5208
15  *
16  * PrivateKeyInfo ::= SEQUENCE {
17  *      version                   Version,
18  *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
19  *      privateKey                PrivateKey,
20  *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
21  * where:
22  * - Version ::= INTEGER
23  * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
24  * - PrivateKey ::= OCTET STRING
25  * - Attributes ::= SET OF Attribute
26  *
27  * EncryptedPrivateKeyInfo ::= SEQUENCE {
28  *        encryptionAlgorithm  EncryptionAlgorithmIdentifier,
29  *        encryptedData        EncryptedData }
30  * where:
31  * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
32  * - EncryptedData ::= OCTET STRING
33  */
34 
35 /**
36   Import an RSAPrivateKey in PKCS#8 format
37   @param in        The packet to import from
38   @param inlen     It's length (octets)
39   @param passwd    The password for decrypting privkey
40   @param passwdlen Password's length (octets)
41   @param key       [out] Destination for newly imported key
42   @return CRYPT_OK if successful, upon error allocated memory is freed
43 */
rsa_import_pkcs8(const unsigned char * in,unsigned long inlen,const void * passwd,unsigned long passwdlen,rsa_key * key)44 int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
45                      const void *passwd, unsigned long passwdlen,
46                      rsa_key *key)
47 {
48    int           err;
49    unsigned char *buf1 = NULL, *buf2 = NULL;
50    unsigned long buf1len, buf2len;
51    unsigned long oid[16], version;
52    const char    *rsaoid;
53    ltc_asn1_list alg_seq[2], top_seq[3];
54    ltc_asn1_list *l = NULL;
55    unsigned char *decrypted = NULL;
56    unsigned long decryptedlen;
57 
58    LTC_ARGCHK(in          != NULL);
59    LTC_ARGCHK(key         != NULL);
60    LTC_ARGCHK(ltc_mp.name != NULL);
61 
62    /* get RSA alg oid */
63    err = pk_get_oid(LTC_OID_RSA, &rsaoid);
64    if (err != CRYPT_OK) { goto LBL_NOFREE; }
65 
66    /* alloc buffers */
67    buf1len = inlen; /* approx. */
68    buf1 = XMALLOC(buf1len);
69    if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; }
70    buf2len = inlen; /* approx. */
71    buf2 = XMALLOC(buf2len);
72    if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
73 
74    /* init key */
75    if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; }
76 
77    /* try to decode encrypted priv key */
78    if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) {
79       goto LBL_ERR;
80    }
81    decrypted    = l->data;
82    decryptedlen = l->size;
83 
84    /* try to decode unencrypted priv key */
85    LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
86    LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);
87    LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL);
88    LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
89    LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
90    err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
91    if (err != CRYPT_OK) { goto LBL_ERR; }
92 
93    /* check alg oid */
94    if ((err = pk_oid_cmp_with_asn1(rsaoid, &alg_seq[0])) != CRYPT_OK) {
95       goto LBL_ERR;
96    }
97 
98    if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) {
99       goto LBL_ERR;
100    }
101    key->type = PK_PRIVATE;
102    err = CRYPT_OK;
103    goto LBL_FREE2;
104 
105 LBL_ERR:
106    rsa_free(key);
107 LBL_FREE2:
108    if (l) der_free_sequence_flexi(l);
109    XFREE(buf2);
110 LBL_FREE1:
111    XFREE(buf1);
112 LBL_NOFREE:
113    return err;
114 }
115 
116 #endif /* LTC_MRSA */
117