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 
11 #include "tomcrypt_private.h"
12 
13 #ifdef LTC_MDH
14 
15 /**
16   Import a DH key from a binary packet
17   @param in     The packet to read
18   @param inlen  The length of the input packet
19   @param key    [out] Where to import the key to
20   @return CRYPT_OK if successful, on error all allocated memory is freed automatically
21 */
dh_import(const unsigned char * in,unsigned long inlen,dh_key * key)22 int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
23 {
24    unsigned char flags[1];
25    int err;
26    unsigned long version;
27 
28    LTC_ARGCHK(in  != NULL);
29    LTC_ARGCHK(key != NULL);
30 
31    /* init */
32    if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
33       return err;
34    }
35 
36    /* find out what type of key it is */
37    err = der_decode_sequence_multi(in, inlen,
38                                    LTC_ASN1_SHORT_INTEGER, 1UL, &version,
39                                    LTC_ASN1_BIT_STRING, 1UL, &flags,
40                                    LTC_ASN1_EOL, 0UL, NULL);
41    if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
42       goto error;
43    }
44 
45    if (version == 0) {
46       if (flags[0] == 1) {
47          key->type = PK_PRIVATE;
48          if ((err = der_decode_sequence_multi(in, inlen,
49                                               LTC_ASN1_SHORT_INTEGER, 1UL, &version,
50                                               LTC_ASN1_BIT_STRING,    1UL, flags,
51                                               LTC_ASN1_INTEGER,       1UL, key->prime,
52                                               LTC_ASN1_INTEGER,       1UL, key->base,
53                                               LTC_ASN1_INTEGER,       1UL, key->x,
54                                               LTC_ASN1_EOL,           0UL, NULL)) != CRYPT_OK) {
55             goto error;
56          }
57          /* compute public key: y = (base ^ x) mod prime */
58          if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
59             goto error;
60          }
61       }
62       else if (flags[0] == 0) {
63          key->type = PK_PUBLIC;
64          if ((err = der_decode_sequence_multi(in, inlen,
65                                               LTC_ASN1_SHORT_INTEGER, 1UL, &version,
66                                               LTC_ASN1_BIT_STRING,    1UL, flags,
67                                               LTC_ASN1_INTEGER,       1UL, key->prime,
68                                               LTC_ASN1_INTEGER,       1UL, key->base,
69                                               LTC_ASN1_INTEGER,       1UL, key->y,
70                                               LTC_ASN1_EOL,           0UL, NULL)) != CRYPT_OK) {
71             goto error;
72          }
73       }
74       else {
75          err = CRYPT_INVALID_PACKET;
76          goto error;
77       }
78    }
79    else {
80       err = CRYPT_INVALID_PACKET;
81       goto error;
82    }
83 
84    /* check public key */
85    if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
86       goto error;
87    }
88 
89    return CRYPT_OK;
90 
91 error:
92    dh_free(key);
93    return err;
94 }
95 
96 #endif /* LTC_MDH */
97 
98 /* ref:         $Format:%D$ */
99 /* git commit:  $Format:%H$ */
100 /* commit time: $Format:%ai$ */
101