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