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.c
14 Import a PKCS RSA key, Tom St Denis
15 */
16
17 #ifdef LTC_MRSA
18
19 /**
20 Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1]
21 @param in The packet to import from
22 @param inlen It's length (octets)
23 @param key [out] Destination for newly imported key
24 @return CRYPT_OK if successful, upon error allocated memory is freed
25 */
rsa_import(const unsigned char * in,unsigned long inlen,rsa_key * key)26 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
27 {
28 int err;
29 void *zero;
30 unsigned char *tmpbuf=NULL;
31 unsigned long tmpbuf_len, len;
32
33 LTC_ARGCHK(in != NULL);
34 LTC_ARGCHK(key != NULL);
35 LTC_ARGCHK(ltc_mp.name != NULL);
36
37 /* init key */
38 if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
39 &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
40 return err;
41 }
42
43 /* see if the OpenSSL DER format RSA public key will work */
44 tmpbuf_len = inlen;
45 tmpbuf = XCALLOC(1, tmpbuf_len);
46 if (tmpbuf == NULL) {
47 err = CRYPT_MEM;
48 goto LBL_ERR;
49 }
50
51 len = 0;
52 err = x509_decode_subject_public_key_info(in, inlen,
53 PKA_RSA, tmpbuf, &tmpbuf_len,
54 LTC_ASN1_NULL, NULL, &len);
55
56 if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
57
58 /* now it should be SEQUENCE { INTEGER, INTEGER } */
59 if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
60 LTC_ASN1_INTEGER, 1UL, key->N,
61 LTC_ASN1_INTEGER, 1UL, key->e,
62 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
63 goto LBL_ERR;
64 }
65 key->type = PK_PUBLIC;
66 err = CRYPT_OK;
67 goto LBL_FREE;
68 }
69
70 /* not SSL public key, try to match against PKCS #1 standards */
71 err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N,
72 LTC_ASN1_EOL, 0UL, NULL);
73
74 if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
75 goto LBL_ERR;
76 }
77
78 if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
79 if ((err = mp_init(&zero)) != CRYPT_OK) {
80 goto LBL_ERR;
81 }
82 /* it's a private key */
83 if ((err = der_decode_sequence_multi(in, inlen,
84 LTC_ASN1_INTEGER, 1UL, zero,
85 LTC_ASN1_INTEGER, 1UL, key->N,
86 LTC_ASN1_INTEGER, 1UL, key->e,
87 LTC_ASN1_INTEGER, 1UL, key->d,
88 LTC_ASN1_INTEGER, 1UL, key->p,
89 LTC_ASN1_INTEGER, 1UL, key->q,
90 LTC_ASN1_INTEGER, 1UL, key->dP,
91 LTC_ASN1_INTEGER, 1UL, key->dQ,
92 LTC_ASN1_INTEGER, 1UL, key->qP,
93 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
94 mp_clear(zero);
95 goto LBL_ERR;
96 }
97 mp_clear(zero);
98 key->type = PK_PRIVATE;
99 } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {
100 /* we don't support multi-prime RSA */
101 err = CRYPT_PK_INVALID_TYPE;
102 goto LBL_ERR;
103 } else {
104 /* it's a public key and we lack e */
105 if ((err = der_decode_sequence_multi(in, inlen,
106 LTC_ASN1_INTEGER, 1UL, key->N,
107 LTC_ASN1_INTEGER, 1UL, key->e,
108 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
109 goto LBL_ERR;
110 }
111 key->type = PK_PUBLIC;
112 }
113 err = CRYPT_OK;
114 goto LBL_FREE;
115
116 LBL_ERR:
117 mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
118
119 LBL_FREE:
120 if (tmpbuf != NULL) {
121 XFREE(tmpbuf);
122 }
123 return err;
124 }
125
126 #endif /* LTC_MRSA */
127
128
129 /* ref: $Format:%D$ */
130 /* git commit: $Format:%H$ */
131 /* commit time: $Format:%ai$ */
132