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 /**
13 @file rsa_import_pkcs8.c
14 Import a PKCS RSA key
15 */
16
17 #ifdef LTC_MRSA
18
19 /* Public-Key Cryptography Standards (PKCS) #8:
20 * Private-Key Information Syntax Specification Version 1.2
21 * https://tools.ietf.org/html/rfc5208
22 *
23 * PrivateKeyInfo ::= SEQUENCE {
24 * version Version,
25 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
26 * privateKey PrivateKey,
27 * attributes [0] IMPLICIT Attributes OPTIONAL }
28 * where:
29 * - Version ::= INTEGER
30 * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
31 * - PrivateKey ::= OCTET STRING
32 * - Attributes ::= SET OF Attribute
33 *
34 * EncryptedPrivateKeyInfo ::= SEQUENCE {
35 * encryptionAlgorithm EncryptionAlgorithmIdentifier,
36 * encryptedData EncryptedData }
37 * where:
38 * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
39 * - EncryptedData ::= OCTET STRING
40 */
41
42 /**
43 Import an RSAPrivateKey in PKCS#8 format
44 @param in The packet to import from
45 @param inlen It's length (octets)
46 @param passwd The password for decrypting privkey
47 @param passwdlen Password's length (octets)
48 @param key [out] Destination for newly imported key
49 @return CRYPT_OK if successful, upon error allocated memory is freed
50 */
rsa_import_pkcs8(const unsigned char * in,unsigned long inlen,const void * passwd,unsigned long passwdlen,rsa_key * key)51 int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
52 const void *passwd, unsigned long passwdlen,
53 rsa_key *key)
54 {
55 int err;
56 void *zero, *iter;
57 unsigned char *buf1 = NULL, *buf2 = NULL;
58 unsigned long buf1len, buf2len;
59 unsigned long oid[16];
60 const char *rsaoid;
61 ltc_asn1_list alg_seq[2], top_seq[3];
62 ltc_asn1_list *l = NULL;
63 unsigned char *decrypted = NULL;
64 unsigned long decryptedlen;
65
66 LTC_ARGCHK(in != NULL);
67 LTC_ARGCHK(key != NULL);
68 LTC_ARGCHK(ltc_mp.name != NULL);
69
70 /* get RSA alg oid */
71 err = pk_get_oid(PKA_RSA, &rsaoid);
72 if (err != CRYPT_OK) { goto LBL_NOFREE; }
73
74 /* alloc buffers */
75 buf1len = inlen; /* approx. */
76 buf1 = XMALLOC(buf1len);
77 if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; }
78 buf2len = inlen; /* approx. */
79 buf2 = XMALLOC(buf2len);
80 if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
81
82 /* init key */
83 err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, &zero, &iter, NULL);
84 if (err != CRYPT_OK) { goto LBL_FREE2; }
85
86 /* try to decode encrypted priv key */
87 if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) {
88 goto LBL_ERR;
89 }
90 decrypted = l->data;
91 decryptedlen = l->size;
92
93 /* try to decode unencrypted priv key */
94 LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
95 LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);
96 LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
97 LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
98 LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
99 err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
100 if (err != CRYPT_OK) { goto LBL_ERR; }
101
102 /* check alg oid */
103 if ((err = pk_oid_cmp_with_asn1(rsaoid, &alg_seq[0])) != CRYPT_OK) {
104 goto LBL_ERR;
105 }
106
107 err = der_decode_sequence_multi(buf1, top_seq[2].size,
108 LTC_ASN1_INTEGER, 1UL, zero,
109 LTC_ASN1_INTEGER, 1UL, key->N,
110 LTC_ASN1_INTEGER, 1UL, key->e,
111 LTC_ASN1_INTEGER, 1UL, key->d,
112 LTC_ASN1_INTEGER, 1UL, key->p,
113 LTC_ASN1_INTEGER, 1UL, key->q,
114 LTC_ASN1_INTEGER, 1UL, key->dP,
115 LTC_ASN1_INTEGER, 1UL, key->dQ,
116 LTC_ASN1_INTEGER, 1UL, key->qP,
117 LTC_ASN1_EOL, 0UL, NULL);
118 if (err != CRYPT_OK) { goto LBL_ERR; }
119 key->type = PK_PRIVATE;
120 err = CRYPT_OK;
121 goto LBL_FREE2;
122
123 LBL_ERR:
124 rsa_free(key);
125 LBL_FREE2:
126 if (l) der_free_sequence_flexi(l);
127 mp_clear_multi(iter, zero, NULL);
128 XFREE(buf2);
129 LBL_FREE1:
130 XFREE(buf1);
131 LBL_NOFREE:
132 return err;
133 }
134
135 #endif /* LTC_MRSA */
136
137 /* ref: $Format:%D$ */
138 /* git commit: $Format:%H$ */
139 /* commit time: $Format:%ai$ */
140