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, 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, PKA_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