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