1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file dsa_decrypt_key.c
7   DSA Crypto, Tom St Denis
8 */
9 
10 #ifdef LTC_MDSA
11 
12 /**
13   Decrypt an DSA encrypted key
14   @param in       The ciphertext
15   @param inlen    The length of the ciphertext (octets)
16   @param out      [out] The plaintext
17   @param outlen   [in/out] The max size and resulting size of the plaintext
18   @param key      The corresponding private DSA key
19   @return CRYPT_OK if successful
20 */
dsa_decrypt_key(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,const dsa_key * key)21 int dsa_decrypt_key(const unsigned char *in,  unsigned long  inlen,
22                           unsigned char *out, unsigned long *outlen,
23                     const dsa_key       *key)
24 {
25    unsigned char  *skey, *expt;
26    void           *g_pub;
27    unsigned long  x, y;
28    unsigned long  hashOID[32] = { 0 };
29    int            hash, err;
30    ltc_asn1_list  decode[3];
31 
32    LTC_ARGCHK(in     != NULL);
33    LTC_ARGCHK(out    != NULL);
34    LTC_ARGCHK(outlen != NULL);
35    LTC_ARGCHK(key    != NULL);
36 
37    /* right key type? */
38    if (key->type != PK_PRIVATE) {
39       return CRYPT_PK_NOT_PRIVATE;
40    }
41 
42    /* decode to find out hash */
43    LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
44    err = der_decode_sequence(in, inlen, decode, 1);
45    if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
46       return err;
47    }
48 
49    hash = find_hash_oid(hashOID, decode[0].size);
50    if (hash_is_valid(hash) != CRYPT_OK) {
51       return CRYPT_INVALID_PACKET;
52    }
53 
54    /* we now have the hash! */
55 
56    if ((err = mp_init(&g_pub)) != CRYPT_OK) {
57       return err;
58    }
59 
60    /* allocate memory */
61    expt   = XMALLOC(mp_unsigned_bin_size(key->p) + 1);
62    skey   = XMALLOC(MAXBLOCKSIZE);
63    if (expt == NULL || skey == NULL) {
64       if (expt != NULL) {
65          XFREE(expt);
66       }
67       if (skey != NULL) {
68          XFREE(skey);
69       }
70       mp_clear(g_pub);
71       return CRYPT_MEM;
72    }
73 
74    LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER,          g_pub,      1UL);
75    LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING,      skey,      MAXBLOCKSIZE);
76 
77    /* read the structure in now */
78    if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
79       goto LBL_ERR;
80    }
81 
82    /* make shared key */
83    x = mp_unsigned_bin_size(key->p) + 1;
84    if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) {
85       goto LBL_ERR;
86    }
87 
88    y = mp_unsigned_bin_size(key->p) + 1;
89    y = MIN(y, MAXBLOCKSIZE);
90    if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) {
91       goto LBL_ERR;
92    }
93 
94    /* ensure the hash of the shared secret is at least as big as the encrypt itself */
95    if (decode[2].size > y) {
96       err = CRYPT_INVALID_PACKET;
97       goto LBL_ERR;
98    }
99 
100    /* avoid buffer overflow */
101    if (*outlen < decode[2].size) {
102       *outlen = decode[2].size;
103       err = CRYPT_BUFFER_OVERFLOW;
104       goto LBL_ERR;
105    }
106 
107    /* Decrypt the key */
108    for (x = 0; x < decode[2].size; x++) {
109      out[x] = expt[x] ^ skey[x];
110    }
111    *outlen = x;
112 
113    err = CRYPT_OK;
114 LBL_ERR:
115 #ifdef LTC_CLEAN_STACK
116    zeromem(expt,   mp_unsigned_bin_size(key->p) + 1);
117    zeromem(skey,   MAXBLOCKSIZE);
118 #endif
119 
120    XFREE(expt);
121    XFREE(skey);
122 
123    mp_clear(g_pub);
124 
125    return err;
126 }
127 
128 #endif
129 
130