/* functions to change the RAND_METHOD */
int change_rand(void);
int restore_rand(void);
-int fbytes(unsigned char *buf, size_t num);
+int fbytes(unsigned char *buf, int num);
RAND_METHOD fake_rand;
const RAND_METHOD *old_rand;
return 1;
}
-static int fbytes_counter = 0;
+static int fbytes_counter = 0, use_fake = 0;
static const char *numbers[8] = {
"651056770906015076056810763456358567190100156695615665659",
"6140507067065001063065065565667405560006161556565665656654",
"1712787255652165239672857892369562652652652356758119494040"
"40041670216363"};
-int fbytes(unsigned char *buf, size_t num)
+int fbytes(unsigned char *buf, int num)
{
int ret;
BIGNUM *tmp = NULL;
+ if (use_fake == 0)
+ return old_rand->bytes(buf, num);
+
+ use_fake = 0;
+
if (fbytes_counter >= 8)
return 0;
tmp = BN_new();
return 0;
}
fbytes_counter ++;
- ret = BN_bn2bin(tmp, buf);
- if (ret == 0 || ret != num)
+ if (num != BN_num_bytes(tmp) || !BN_bn2bin(tmp, buf))
ret = 0;
- else
+ else
ret = 1;
if (tmp)
BN_free(tmp);
EVP_MD_CTX_init(&md_ctx);
/* get the message digest */
- EVP_DigestInit(&md_ctx, EVP_ecdsa());
- EVP_DigestUpdate(&md_ctx, (const void*)message, 3);
- EVP_DigestFinal(&md_ctx, digest, &dgst_len);
+ if (!EVP_DigestInit(&md_ctx, EVP_ecdsa())
+ || !EVP_DigestUpdate(&md_ctx, (const void*)message, 3)
+ || !EVP_DigestFinal(&md_ctx, digest, &dgst_len))
+ goto x962_int_err;
BIO_printf(out, "testing %s: ", OBJ_nid2sn(nid));
/* create the key */
if ((key = EC_KEY_new_by_curve_name(nid)) == NULL)
goto x962_int_err;
+ use_fake = 1;
if (!EC_KEY_generate_key(key))
goto x962_int_err;
BIO_printf(out, ".");
(void)BIO_flush(out);
/* create the signature */
+ use_fake = 1;
signature = ECDSA_do_sign(digest, 20, key);
if (signature == NULL)
goto x962_int_err;
"3238135532097973577080787768312505059318910517550078427819"
"78505179448783"))
goto x962_err;
+#ifndef OPENSSL_NO_EC2M
if (!x9_62_test_internal(out, NID_X9_62_c2tnb191v1,
"87194383164871543355722284926904419997237591535066528048",
"308992691965804947361541664549085895292153777025772063598"))
"1970303740007316867383349976549972270528498040721988191026"
"49413465737174"))
goto x962_err;
-
+#endif
ret = 1;
x962_err:
if (!restore_rand())
size_t crv_len = 0, n = 0;
EC_KEY *eckey = NULL, *wrong_eckey = NULL;
EC_GROUP *group;
+ ECDSA_SIG *ecdsa_sig = NULL;
unsigned char digest[20], wrong_digest[20];
- unsigned char *signature = NULL;
- unsigned int sig_len;
+ unsigned char *signature = NULL;
+ unsigned char *sig_ptr;
+ unsigned char *raw_buf = NULL;
+ unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len;
int nid, ret = 0;
/* fill digest values with some random data */
if (EC_KEY_set_group(eckey, group) == 0)
goto builtin_err;
EC_GROUP_free(group);
- if (EC_GROUP_get_degree(EC_KEY_get0_group(eckey)) < 160)
+ degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey));
+ if (degree < 160)
/* drop the curve */
{
EC_KEY_free(eckey);
}
BIO_printf(out, ".");
(void)BIO_flush(out);
- /* modify a single byte of the signature */
- offset = signature[10] % sig_len;
- dirt = signature[11];
- signature[offset] ^= dirt ? dirt : 1;
+ /* wrong length */
+ if (ECDSA_verify(0, digest, 20, signature, sig_len - 1,
+ eckey) == 1)
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+
+ /* Modify a single byte of the signature: to ensure we don't
+ * garble the ASN1 structure, we read the raw signature and
+ * modify a byte in one of the bignums directly. */
+ sig_ptr = signature;
+ if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL)
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+
+ /* Store the two BIGNUMs in raw_buf. */
+ r_len = BN_num_bytes(ecdsa_sig->r);
+ s_len = BN_num_bytes(ecdsa_sig->s);
+ bn_len = (degree + 7) / 8;
+ if ((r_len > bn_len) || (s_len > bn_len))
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ buf_len = 2 * bn_len;
+ if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL)
+ goto builtin_err;
+ /* Pad the bignums with leading zeroes. */
+ memset(raw_buf, 0, buf_len);
+ BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len);
+ BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len);
+
+ /* Modify a single byte in the buffer. */
+ offset = raw_buf[10] % buf_len;
+ dirt = raw_buf[11] ? raw_buf[11] : 1;
+ raw_buf[offset] ^= dirt;
+ /* Now read the BIGNUMs back in from raw_buf. */
+ if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) ||
+ (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL))
+ goto builtin_err;
+
+ sig_ptr = signature;
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr);
if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1)
{
BIO_printf(out, " failed\n");
goto builtin_err;
}
+ /* Sanity check: undo the modification and verify signature. */
+ raw_buf[offset] ^= dirt;
+ if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) ||
+ (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL))
+ goto builtin_err;
+
+ sig_ptr = signature;
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr);
+ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1)
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
BIO_printf(out, ".");
(void)BIO_flush(out);
BIO_printf(out, " ok\n");
/* cleanup */
+ /* clean bogus errors */
+ ERR_clear_error();
OPENSSL_free(signature);
signature = NULL;
EC_KEY_free(eckey);
eckey = NULL;
EC_KEY_free(wrong_eckey);
wrong_eckey = NULL;
+ ECDSA_SIG_free(ecdsa_sig);
+ ecdsa_sig = NULL;
+ OPENSSL_free(raw_buf);
+ raw_buf = NULL;
}
ret = 1;
EC_KEY_free(eckey);
if (wrong_eckey)
EC_KEY_free(wrong_eckey);
+ if (ecdsa_sig)
+ ECDSA_SIG_free(ecdsa_sig);
if (signature)
OPENSSL_free(signature);
+ if (raw_buf)
+ OPENSSL_free(raw_buf);
if (curves)
OPENSSL_free(curves);