1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 #include "tomcrypt_private.h"
5 
6 #ifdef LTC_MDH
7 
8 /**
9   Import a DH key from a binary packet
10   @param in     The packet to read
11   @param inlen  The length of the input packet
12   @param key    [out] Where to import the key to
13   @return CRYPT_OK if successful, on error all allocated memory is freed automatically
14 */
dh_import(const unsigned char * in,unsigned long inlen,dh_key * key)15 int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
16 {
17    unsigned char flags[1];
18    int err;
19    unsigned long version;
20 
21    LTC_ARGCHK(in  != NULL);
22    LTC_ARGCHK(key != NULL);
23 
24    /* init */
25    if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
26       return err;
27    }
28 
29    /* find out what type of key it is */
30    err = der_decode_sequence_multi(in, inlen,
31                                    LTC_ASN1_SHORT_INTEGER, 1UL, &version,
32                                    LTC_ASN1_BIT_STRING, 1UL, &flags,
33                                    LTC_ASN1_EOL, 0UL, NULL);
34    if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
35       goto error;
36    }
37 
38    if (version == 0) {
39       if (flags[0] == 1) {
40          key->type = PK_PRIVATE;
41          if ((err = der_decode_sequence_multi(in, inlen,
42                                               LTC_ASN1_SHORT_INTEGER, 1UL, &version,
43                                               LTC_ASN1_BIT_STRING,    1UL, flags,
44                                               LTC_ASN1_INTEGER,       1UL, key->prime,
45                                               LTC_ASN1_INTEGER,       1UL, key->base,
46                                               LTC_ASN1_INTEGER,       1UL, key->x,
47                                               LTC_ASN1_EOL,           0UL, NULL)) != CRYPT_OK) {
48             goto error;
49          }
50          /* compute public key: y = (base ^ x) mod prime */
51          if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
52             goto error;
53          }
54       }
55       else if (flags[0] == 0) {
56          key->type = PK_PUBLIC;
57          if ((err = der_decode_sequence_multi(in, inlen,
58                                               LTC_ASN1_SHORT_INTEGER, 1UL, &version,
59                                               LTC_ASN1_BIT_STRING,    1UL, flags,
60                                               LTC_ASN1_INTEGER,       1UL, key->prime,
61                                               LTC_ASN1_INTEGER,       1UL, key->base,
62                                               LTC_ASN1_INTEGER,       1UL, key->y,
63                                               LTC_ASN1_EOL,           0UL, NULL)) != CRYPT_OK) {
64             goto error;
65          }
66       }
67       else {
68          err = CRYPT_INVALID_PACKET;
69          goto error;
70       }
71    }
72    else {
73       err = CRYPT_INVALID_PACKET;
74       goto error;
75    }
76 
77    /* check public key */
78    if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
79       goto error;
80    }
81 
82    return CRYPT_OK;
83 
84 error:
85    dh_free(key);
86    return err;
87 }
88 
89 #endif /* LTC_MDH */
90