diff options
author | Matt Johnston <matt@ucc.asn.au> | 2018-02-17 19:29:51 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2018-02-17 19:29:51 +0800 |
commit | 7e8094d53a1c01ac671156ff2e67157b64d01a3a (patch) | |
tree | c88345f5bdd118eb9414dff5ab5c307bb1806c57 /libtomcrypt/src/pk/dsa/dsa_import.c | |
parent | f7a664f127d3dfde0e7c7a9ca74b1d14f9a2f983 (diff) | |
parent | f042eb41ab0d31f8ba0c5ccc9c848ad01f08f986 (diff) |
merge from main
--HG--
branch : fuzz
Diffstat (limited to 'libtomcrypt/src/pk/dsa/dsa_import.c')
-rw-r--r-- | libtomcrypt/src/pk/dsa/dsa_import.c | 138 |
1 files changed, 100 insertions, 38 deletions
diff --git a/libtomcrypt/src/pk/dsa/dsa_import.c b/libtomcrypt/src/pk/dsa/dsa_import.c index 47a68ca..e6a7560 100644 --- a/libtomcrypt/src/pk/dsa/dsa_import.c +++ b/libtomcrypt/src/pk/dsa/dsa_import.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,7 +16,7 @@ #ifdef LTC_MDSA /** - Import a DSA key + Import a DSA key @param in The binary packet to import from @param inlen The length of the binary packet @param key [out] Where to store the imported key @@ -26,8 +24,10 @@ */ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) { + int err, stat; + unsigned long zero = 0; + unsigned char* tmpbuf = NULL; unsigned char flags[1]; - int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); @@ -38,53 +38,115 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) return CRYPT_MEM; } + /* try to match the old libtomcrypt format */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) { + /* private key */ + if (flags[0] == 1) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PRIVATE; + goto LBL_OK; + } + /* public key */ + else if (flags[0] == 0) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PUBLIC; + goto LBL_OK; + } + else { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } /* get key type */ if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; - } + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + + key->type = PK_PRIVATE; + } else { /* public */ + ltc_asn1_list params[3]; + unsigned long tmpbuf_len = inlen; + + LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } - if (flags[0] == 1) { - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; + err = der_decode_subject_public_key_info(in, inlen, PKA_DSA, + tmpbuf, &tmpbuf_len, + LTC_ASN1_SEQUENCE, params, 3); + if (err != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; } - key->type = PK_PRIVATE; - } else { - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; + + if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; } + + XFREE(tmpbuf); key->type = PK_PUBLIC; - } - key->qord = mp_unsigned_bin_size(key->q); + } + +LBL_OK: + key->qord = mp_unsigned_bin_size(key->q); - if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || - (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) { + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + /* validate x, y */ + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { err = CRYPT_INVALID_PACKET; - goto error; + goto LBL_ERR; } return CRYPT_OK; -error: - mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL); +LBL_ERR: + dsa_free(key); return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ |