int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) { unsigned long x, y; int err; _ARGCHK(in != NULL); _ARGCHK(key != NULL); /* check length */ if (inlen < 1+PACKET_SIZE) { return CRYPT_INVALID_PACKET; } /* test packet header */ if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) { return err; } /* init key */ if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) { return CRYPT_MEM; } /* get key type */ y = PACKET_SIZE; key->type = (int)in[y++]; /* load the modulus */ INPUT_BIGNUM(&key->N, in, x, y); /* load public exponent */ INPUT_BIGNUM(&key->e, in, x, y); /* get private exponent */ if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) { INPUT_BIGNUM(&key->d, in, x, y); } /* get CRT private data if required */ if (key->type == PK_PRIVATE_OPTIMIZED) { INPUT_BIGNUM(&key->dQ, in, x, y); INPUT_BIGNUM(&key->dP, in, x, y); INPUT_BIGNUM(&key->pQ, in, x, y); INPUT_BIGNUM(&key->qP, in, x, y); INPUT_BIGNUM(&key->p, in, x, y); INPUT_BIGNUM(&key->q, in, x, y); } /* free up ram not required */ if (key->type != PK_PRIVATE_OPTIMIZED) { mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL); } if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { mp_clear(&key->d); } return CRYPT_OK; error2: mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL); return err; }
/** Verify the signature given @param sig The signature @param siglen The length of the signature (octets) @param hash The hash that was signed @param hashlen The length of the hash (octets) @param stat [out] Result of signature comparison, 1==valid, 0==invalid @param key The public DH key that signed the hash @return CRYPT_OK if succsessful (even if signature is invalid) */ int dh_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, dh_key *key) { mp_int a, b, p, g, m, tmp; unsigned long x, y; int err; LTC_ARGCHK(sig != NULL); LTC_ARGCHK(hash != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); /* default to invalid */ *stat = 0; /* check initial input length */ if (siglen < PACKET_SIZE+4+4) { return CRYPT_INVALID_PACKET; } /* header ok? */ if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) { return err; } /* get hash out of packet */ y = PACKET_SIZE; /* init all bignums */ if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) { return mpi_to_ltc_error(err); } /* load a and b */ INPUT_BIGNUM(&a, sig, x, y, siglen); INPUT_BIGNUM(&b, sig, x, y, siglen); /* load p and g */ if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error1; } if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error1; } /* load m */ if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; } /* find g^m mod p */ if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error1; } /* m = g^m mod p */ /* find y^a * a^b */ if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error1; } /* tmp = y^a mod p */ if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error1; } /* a = a^b mod p */ if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error1; } /* a = y^a * a^b mod p */ /* y^a * a^b == g^m ??? */ if (mp_cmp(&a, &m) == 0) { *stat = 1; } /* clean up */ err = CRYPT_OK; goto done; error1: err = mpi_to_ltc_error(err); error: done: mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL); return err; }