summaryrefslogtreecommitdiffhomepage
path: root/libtomcrypt/src/pk/dsa/dsa_import.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtomcrypt/src/pk/dsa/dsa_import.c')
-rw-r--r--libtomcrypt/src/pk/dsa/dsa_import.c138
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$ */