1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file dsa_import.c
7 DSA implementation, import a DSA key, Tom St Denis
8 */
9
10 #ifdef LTC_MDSA
11
12 /**
13 Import a DSA key
14 @param in The binary packet to import from
15 @param inlen The length of the binary packet
16 @param key [out] Where to store the imported key
17 @return CRYPT_OK if successful, upon error this function will free all allocated memory
18 */
dsa_import(const unsigned char * in,unsigned long inlen,dsa_key * key)19 int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
20 {
21 int err, stat;
22 unsigned long zero = 0, len;
23 unsigned char* tmpbuf = NULL;
24 unsigned char flags[1];
25
26 LTC_ARGCHK(in != NULL);
27 LTC_ARGCHK(key != NULL);
28 LTC_ARGCHK(ltc_mp.name != NULL);
29
30 /* init key */
31 if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL) != CRYPT_OK) {
32 return CRYPT_MEM;
33 }
34
35 /* try to match the old libtomcrypt format */
36 err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
37 LTC_ASN1_EOL, 0UL, NULL);
38
39 if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) {
40 /* private key */
41 if (flags[0] == 1) {
42 if ((err = der_decode_sequence_multi(in, inlen,
43 LTC_ASN1_BIT_STRING, 1UL, flags,
44 LTC_ASN1_INTEGER, 1UL, key->g,
45 LTC_ASN1_INTEGER, 1UL, key->p,
46 LTC_ASN1_INTEGER, 1UL, key->q,
47 LTC_ASN1_INTEGER, 1UL, key->y,
48 LTC_ASN1_INTEGER, 1UL, key->x,
49 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
50 goto LBL_ERR;
51 }
52 key->type = PK_PRIVATE;
53 goto LBL_OK;
54 }
55 /* public key */
56 else if (flags[0] == 0) {
57 if ((err = der_decode_sequence_multi(in, inlen,
58 LTC_ASN1_BIT_STRING, 1UL, flags,
59 LTC_ASN1_INTEGER, 1UL, key->g,
60 LTC_ASN1_INTEGER, 1UL, key->p,
61 LTC_ASN1_INTEGER, 1UL, key->q,
62 LTC_ASN1_INTEGER, 1UL, key->y,
63 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
64 goto LBL_ERR;
65 }
66 key->type = PK_PUBLIC;
67 goto LBL_OK;
68 }
69 else {
70 err = CRYPT_INVALID_PACKET;
71 goto LBL_ERR;
72 }
73 }
74 /* get key type */
75 if ((err = der_decode_sequence_multi(in, inlen,
76 LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
77 LTC_ASN1_INTEGER, 1UL, key->p,
78 LTC_ASN1_INTEGER, 1UL, key->q,
79 LTC_ASN1_INTEGER, 1UL, key->g,
80 LTC_ASN1_INTEGER, 1UL, key->y,
81 LTC_ASN1_INTEGER, 1UL, key->x,
82 LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
83
84 key->type = PK_PRIVATE;
85 } else { /* public */
86 ltc_asn1_list params[3];
87 unsigned long tmpbuf_len = inlen;
88
89 LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL);
90 LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL);
91 LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL);
92
93 tmpbuf = XCALLOC(1, tmpbuf_len);
94 if (tmpbuf == NULL) {
95 err = CRYPT_MEM;
96 goto LBL_ERR;
97 }
98
99 len = 3;
100 err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_DSA,
101 tmpbuf, &tmpbuf_len,
102 LTC_ASN1_SEQUENCE, params, &len);
103 if (err != CRYPT_OK) {
104 XFREE(tmpbuf);
105 goto LBL_ERR;
106 }
107
108 if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) {
109 XFREE(tmpbuf);
110 goto LBL_ERR;
111 }
112
113 XFREE(tmpbuf);
114 key->type = PK_PUBLIC;
115 }
116
117 LBL_OK:
118 key->qord = mp_unsigned_bin_size(key->q);
119
120 /* quick p, q, g validation, without primality testing */
121 if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) {
122 goto LBL_ERR;
123 }
124 if (stat == 0) {
125 err = CRYPT_INVALID_PACKET;
126 goto LBL_ERR;
127 }
128 /* validate x, y */
129 if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) {
130 goto LBL_ERR;
131 }
132 if (stat == 0) {
133 err = CRYPT_INVALID_PACKET;
134 goto LBL_ERR;
135 }
136
137 return CRYPT_OK;
138 LBL_ERR:
139 dsa_free(key);
140 return err;
141 }
142
143 #endif
144