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