int test_builtin(BIO *out) { EC_builtin_curve *curves = NULL; size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; unsigned char digest[20], wrong_digest[20]; unsigned char *signature = NULL; unsigned int sig_len; int nid, ret = 0; /* fill digest values with some random data */ if (!RAND_pseudo_bytes(digest, 20) || !RAND_pseudo_bytes(wrong_digest, 20)) { BIO_printf(out, "ERROR: unable to get random data\n"); goto builtin_err; } /* create and verify a ecdsa signature with every availble curve * (with ) */ BIO_printf(out, "\ntesting ECDSA_sign() and ECDSA_verify() " "with some internal curves:\n"); /* get a list of all internal curves */ crv_len = EC_get_builtin_curves(NULL, 0); curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len); if (curves == NULL) { BIO_printf(out, "malloc error\n"); goto builtin_err; } if (!EC_get_builtin_curves(curves, crv_len)) { BIO_printf(out, "unable to get internal curves\n"); goto builtin_err; } /* now create and verify a signature for every curve */ for (n = 0; n < crv_len; n++) { unsigned char dirt, offset; nid = curves[n].nid; if (nid == NID_ipsec4) continue; /* create new ecdsa key (== EC_KEY) */ if ((eckey = EC_KEY_new()) == NULL) goto builtin_err; group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) goto builtin_err; 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) /* drop the curve */ { EC_KEY_free(eckey); eckey = NULL; continue; } BIO_printf(out, "%s: ", OBJ_nid2sn(nid)); /* create key */ if (!EC_KEY_generate_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } /* create second key */ if ((wrong_eckey = EC_KEY_new()) == NULL) goto builtin_err; group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) goto builtin_err; if (EC_KEY_set_group(wrong_eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); if (!EC_KEY_generate_key(wrong_eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* check key */ if (!EC_KEY_check_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* create signature */ sig_len = ECDSA_size(eckey); if ((signature = OPENSSL_malloc(sig_len)) == NULL) goto builtin_err; if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature */ 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); /* verify signature with the wrong key */ if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong digest */ if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } 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; 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 */ OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; } ret = 1; builtin_err: if (eckey) EC_KEY_free(eckey); if (wrong_eckey) EC_KEY_free(wrong_eckey); if (signature) OPENSSL_free(signature); if (curves) OPENSSL_free(curves); return ret; }
int test_builtin(BIO *out) { EC_builtin_curve *curves = NULL; 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; const unsigned char *sig_ptr; unsigned char *sig_ptr2; 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 (RAND_bytes(digest, 20) <= 0 || RAND_bytes(wrong_digest, 20) <= 0) { BIO_printf(out, "ERROR: unable to get random data\n"); goto builtin_err; } /* * create and verify a ecdsa signature with every availble curve (with ) */ BIO_printf(out, "\ntesting ECDSA_sign() and ECDSA_verify() " "with some internal curves:\n"); /* get a list of all internal curves */ crv_len = EC_get_builtin_curves(NULL, 0); curves = OPENSSL_malloc(sizeof(*curves) * crv_len); if (curves == NULL) { BIO_printf(out, "malloc error\n"); goto builtin_err; } if (!EC_get_builtin_curves(curves, crv_len)) { BIO_printf(out, "unable to get internal curves\n"); goto builtin_err; } /* now create and verify a signature for every curve */ for (n = 0; n < crv_len; n++) { unsigned char dirt, offset; nid = curves[n].nid; if (nid == NID_ipsec4) continue; /* create new ecdsa key (== EC_KEY) */ if ((eckey = EC_KEY_new()) == NULL) goto builtin_err; group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) goto builtin_err; if (EC_KEY_set_group(eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); if (degree < 160) { /* drop the curve */ EC_KEY_free(eckey); eckey = NULL; continue; } BIO_printf(out, "%s: ", OBJ_nid2sn(nid)); /* create key */ if (!EC_KEY_generate_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } /* create second key */ if ((wrong_eckey = EC_KEY_new()) == NULL) goto builtin_err; group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) goto builtin_err; if (EC_KEY_set_group(wrong_eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); if (!EC_KEY_generate_key(wrong_eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* check key */ if (!EC_KEY_check_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* create signature */ sig_len = ECDSA_size(eckey); if ((signature = OPENSSL_malloc(sig_len)) == NULL) goto builtin_err; if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature */ 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); /* verify signature with the wrong key */ if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong digest */ if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* 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_zalloc(buf_len)) == NULL) goto builtin_err; 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_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); 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_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); 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; builtin_err: EC_KEY_free(eckey); EC_KEY_free(wrong_eckey); ECDSA_SIG_free(ecdsa_sig); OPENSSL_free(signature); OPENSSL_free(raw_buf); OPENSSL_free(curves); return ret; }
/* call-seq: * OpenSSL::PKey::EC.new() * OpenSSL::PKey::EC.new(ec_key) * OpenSSL::PKey::EC.new(ec_group) * OpenSSL::PKey::EC.new("secp112r1") * OpenSSL::PKey::EC.new(pem_string) * OpenSSL::PKey::EC.new(pem_string [, pwd]) * OpenSSL::PKey::EC.new(der_string) * * See the OpenSSL documentation for: * EC_KEY_* */ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; EC_KEY *ec = NULL; VALUE arg, pass; VALUE group = Qnil; char *passwd = NULL; GetPKey(self, pkey); if (pkey->pkey.ec) ossl_raise(eECError, "EC_KEY already initialized"); rb_scan_args(argc, argv, "02", &arg, &pass); if (NIL_P(arg)) { ec = EC_KEY_new(); } else { if (rb_obj_is_kind_of(arg, cEC)) { EC_KEY *other_ec = NULL; SafeRequire_EC_KEY(arg, other_ec); ec = EC_KEY_dup(other_ec); } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { ec = EC_KEY_new(); group = arg; } else { BIO *in = ossl_obj2bio(arg); if (!NIL_P(pass)) { passwd = StringValuePtr(pass); } ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); if (!ec) { OSSL_BIO_reset(in); ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd); } if (!ec) { OSSL_BIO_reset(in); ec = d2i_ECPrivateKey_bio(in, NULL); } if (!ec) { OSSL_BIO_reset(in); ec = d2i_EC_PUBKEY_bio(in, NULL); } BIO_free(in); if (ec == NULL) { const char *name = StringValueCStr(arg); int nid = OBJ_sn2nid(name); (void)ERR_get_error(); if (nid == NID_undef) ossl_raise(eECError, "unknown curve name (%s)\n", name); if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL) ossl_raise(eECError, "unable to create curve (%s)\n", name); EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); } } } if (ec == NULL) ossl_raise(eECError, NULL); if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { EC_KEY_free(ec); ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); } rb_iv_set(self, "@group", Qnil); if (!NIL_P(group)) rb_funcall(self, rb_intern("group="), 1, arg); return self; }
/* * Get EC key material and stash pointer in ex_data * Note we get called twice, once for private key, and once for public * We need to get the EC_PARAMS and EC_POINT into both, * as lib11 dates from RSA only where all the pub key components * were also part of the private key. With EC the point * is not in the private key, and the params may or may not be. * */ static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY * key) { EVP_PKEY *pk; EC_KEY * ec = NULL; CK_RV ckrv; size_t ec_paramslen = 0; CK_BYTE * ec_params = NULL; size_t ec_pointlen = 0; CK_BYTE * ec_point = NULL; PKCS11_KEY * pubkey; ASN1_OCTET_STRING *os=NULL; pk = EVP_PKEY_new(); if (pk == NULL) return NULL; ec = EC_KEY_new(); if (ec == NULL) { EVP_PKEY_free(pk); return NULL; } EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */ /* For Openssl req we need at least the * EC_KEY_get0_group(ec_key)) to return the group. * Even if it fails will continue as a sign only does not need * need this if the pkcs11 or card can figure this out. */ if (key_getattr_var(key, CKA_EC_PARAMS, NULL, &ec_paramslen) == CKR_OK && ec_paramslen > 0) { ec_params = OPENSSL_malloc(ec_paramslen); if (ec_params) { ckrv = key_getattr_var(key, CKA_EC_PARAMS, ec_params, &ec_paramslen); if (ckrv == CKR_OK) { const unsigned char * a = ec_params; /* convert to OpenSSL parmas */ d2i_ECParameters(&ec, &a, (long) ec_paramslen); } } } /* Now get the ec_point */ pubkey = key->isPrivate ? PKCS11_find_key_from_key(key) : key; if (pubkey) { ckrv = key_getattr_var(pubkey, CKA_EC_POINT, NULL, &ec_pointlen); if (ckrv == CKR_OK && ec_pointlen > 0) { ec_point = OPENSSL_malloc(ec_pointlen); if (ec_point) { ckrv = key_getattr_var(pubkey, CKA_EC_POINT, ec_point, &ec_pointlen); if (ckrv == CKR_OK) { /* PKCS#11 returns ASN1 octstring*/ const unsigned char * a; /* we have asn1 octet string, need to strip off 04 len */ a = ec_point; os = d2i_ASN1_OCTET_STRING(NULL, &a, (long) ec_pointlen); if (os) { a = os->data; o2i_ECPublicKey(&ec, &a, os->length); } /* EC_KEY_print_fp(stderr, ec, 5); */ } } } } /* If the key is not extractable, create a key object * that will use the card's functions to sign & decrypt */ if (os) ASN1_STRING_free(os); if (ec_point) OPENSSL_free(ec_point); if (ec_params) OPENSSL_free(ec_params); if (key->isPrivate) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L EC_KEY_set_method(ec, PKCS11_get_ec_key_method()); #else ECDSA_set_method(ec, PKCS11_get_ecdsa_method()); /* TODO: Retrieve the ECDSA private key object attributes instead, * unless the key has the "sensitive" attribute set */ #endif } /* TODO: Extract the ECDSA private key instead, if the key * is marked as extractable (and not private?) */ #if OPENSSL_VERSION_NUMBER >= 0x10100002L EC_KEY_set_ex_data(ec,ec_key_ex_index, key); #else ECDSA_set_ex_data(ec, ecdsa_ex_index, key); #endif EC_KEY_free(ec); /* drops our reference to it */ return pk; }
static krb5_error_code generate_dh_keyblock(krb5_context context, pk_client_params *client_params, krb5_enctype enctype) { unsigned char *dh_gen_key = NULL; krb5_keyblock key; krb5_error_code ret; size_t dh_gen_keylen, size; memset(&key, 0, sizeof(key)); if (client_params->keyex == USE_DH) { if (client_params->u.dh.public_key == NULL) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "public_key"); goto out; } if (!DH_generate_key(client_params->u.dh.key)) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "Can't generate Diffie-Hellman keys"); goto out; } size = DH_size(client_params->u.dh.key); dh_gen_key = malloc(size); if (dh_gen_key == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } dh_gen_keylen = DH_compute_key(dh_gen_key,client_params->u.dh.public_key, client_params->u.dh.key); if (dh_gen_keylen == (size_t)-1) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "Can't compute Diffie-Hellman key"); goto out; } if (dh_gen_keylen < size) { size -= dh_gen_keylen; memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen); memset(dh_gen_key, 0, size); } ret = 0; #ifdef HAVE_OPENSSL } else if (client_params->keyex == USE_ECDH) { if (client_params->u.ecdh.public_key == NULL) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "public_key"); goto out; } client_params->u.ecdh.key = EC_KEY_new(); if (client_params->u.ecdh.key == NULL) { ret = ENOMEM; goto out; } EC_KEY_set_group(client_params->u.ecdh.key, EC_KEY_get0_group(client_params->u.ecdh.public_key)); if (EC_KEY_generate_key(client_params->u.ecdh.key) != 1) { ret = ENOMEM; goto out; } size = (EC_GROUP_get_degree(EC_KEY_get0_group(client_params->u.ecdh.key)) + 7) / 8; dh_gen_key = malloc(size); if (dh_gen_key == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out; } dh_gen_keylen = ECDH_compute_key(dh_gen_key, size, EC_KEY_get0_public_key(client_params->u.ecdh.public_key), client_params->u.ecdh.key, NULL); #endif /* HAVE_OPENSSL */ } else { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "Diffie-Hellman not selected keys"); goto out; } ret = _krb5_pk_octetstring2key(context, enctype, dh_gen_key, dh_gen_keylen, NULL, NULL, &client_params->reply_key); out: if (dh_gen_key) free(dh_gen_key); if (key.keyvalue.data) krb5_free_keyblock_contents(context, &key); return ret; }
int generatePem(char **pem) { int returnError = NOERROR; char * errorMessage = ""; char *pemholder = calloc(240, sizeof(char)); EC_KEY *eckey = NULL; BIO *out = NULL; BUF_MEM *buf = NULL; EC_GROUP *group = NULL; if ((out = BIO_new(BIO_s_mem())) == NULL) { returnError = ERROR; errorMessage = "Error in BIO_new(BIO_s_mem())"; goto clearVariables; } if ((group = EC_GROUP_new_by_curve_name(NID_secp256k1)) == NULL) { returnError = ERROR; errorMessage = "Error in EC_GROUP_new_by_curve_name(NID_secp256k1))"; goto clearVariables; } if (((eckey = EC_KEY_new()) == NULL) || ((buf = BUF_MEM_new()) == NULL)) { returnError = ERROR; errorMessage = "Error in EC_KEY_new())"; goto clearVariables; }; if (createNewKey(group, eckey) == ERROR) { returnError = ERROR; errorMessage = "Error in createNewKey(group, eckey)"; goto clearVariables; } if (PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL) == 0) { returnError = ERROR; errorMessage = "Error in PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL)"; goto clearVariables; } BIO_get_mem_ptr(out, &buf); memcpy(pemholder, buf->data, 224); if (buf->data[218] == '\n') { pemholder[219] = '\0'; memcpy(*pem, pemholder, 220); } else if ( buf->data[219] == '\n') { pemholder[220] = '\0'; memcpy(*pem, pemholder, 221); } else if ( buf->data[221] == '\n') { pemholder[222] = '\0'; memcpy(*pem, pemholder, 223); } else if (buf->data[222] == '\n') { pemholder[223] = '\0'; memcpy(*pem, pemholder, 224); } else { returnError = ERROR; errorMessage = "Invalid PEM generated"; goto clearVariables; } goto clearVariables; clearVariables: if (group != NULL) EC_GROUP_clear_free(group); if (pemholder != NULL) free(pemholder); if (eckey != NULL) EC_KEY_free(eckey); if (out != NULL) BIO_free_all(out); if (errorMessage[0] != '\0') printf("Error: %s\n", errorMessage); return returnError; };
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { EVP_PKEY *pkey = NULL; #ifndef OPENSSL_NO_RSA RSA *rsa = NULL; #endif #ifndef OPENSSL_NO_DSA DSA *dsa = NULL; ASN1_TYPE *t1, *t2; ASN1_INTEGER *privkey; STACK_OF(ASN1_TYPE) *ndsa = NULL; #endif #ifndef OPENSSL_NO_EC EC_KEY *eckey = NULL; const unsigned char *p_tmp; #endif #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) ASN1_TYPE *param = NULL; BN_CTX *ctx = NULL; int plen; #endif X509_ALGOR *a; const unsigned char *p; const unsigned char *cp; int pkeylen; int nid; char obj_tmp[80]; if(p8->pkey->type == V_ASN1_OCTET_STRING) { p8->broken = PKCS8_OK; p = p8->pkey->value.octet_string->data; pkeylen = p8->pkey->value.octet_string->length; } else { p8->broken = PKCS8_NO_OCTET; p = p8->pkey->value.sequence->data; pkeylen = p8->pkey->value.sequence->length; } if (!(pkey = EVP_PKEY_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); return NULL; } a = p8->pkeyalg; nid = OBJ_obj2nid(a->algorithm); switch(nid) { #ifndef OPENSSL_NO_RSA case NID_rsaEncryption: cp = p; if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); return NULL; } EVP_PKEY_assign_RSA (pkey, rsa); break; #endif #ifndef OPENSSL_NO_DSA case NID_dsa: /* PKCS#8 DSA is weird: you just get a private key integer * and parameters in the AlgorithmIdentifier the pubkey must * be recalculated. */ /* Check for broken DSA PKCS#8, UGH! */ if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, d2i_ASN1_TYPE, ASN1_TYPE_free))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } if(sk_ASN1_TYPE_num(ndsa) != 2 ) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } /* Handle Two broken types: * SEQUENCE {parameters, priv_key} * SEQUENCE {pub_key, priv_key} */ t1 = sk_ASN1_TYPE_value(ndsa, 0); t2 = sk_ASN1_TYPE_value(ndsa, 1); if(t1->type == V_ASN1_SEQUENCE) { p8->broken = PKCS8_EMBEDDED_PARAM; param = t1; } else if(a->parameter->type == V_ASN1_SEQUENCE) { p8->broken = PKCS8_NS_DB; param = a->parameter; } else { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } if(t2->type != V_ASN1_INTEGER) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } privkey = t2->value.integer; } else { if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } param = p8->pkeyalg->parameter; } if (!param || (param->type != V_ASN1_SEQUENCE)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } cp = p = param->value.sequence->data; plen = param->value.sequence->length; if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } /* We have parameters now set private key */ if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); goto dsaerr; } /* Calculate public key (ouch!) */ if (!(dsa->pub_key = BN_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); goto dsaerr; } if (!(ctx = BN_CTX_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); goto dsaerr; } if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); goto dsaerr; } EVP_PKEY_assign_DSA(pkey, dsa); BN_CTX_free (ctx); if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); else ASN1_INTEGER_free(privkey); break; dsaerr: BN_CTX_free (ctx); sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); DSA_free(dsa); EVP_PKEY_free(pkey); return NULL; break; #endif #ifndef OPENSSL_NO_EC case NID_X9_62_id_ecPublicKey: p_tmp = p; /* extract the ec parameters */ param = p8->pkeyalg->parameter; if (!param || ((param->type != V_ASN1_SEQUENCE) && (param->type != V_ASN1_OBJECT))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } if (param->type == V_ASN1_SEQUENCE) { cp = p = param->value.sequence->data; plen = param->value.sequence->length; if (!(eckey = d2i_ECParameters(NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } } else { EC_GROUP *group; cp = p = param->value.object->data; plen = param->value.object->length; /* type == V_ASN1_OBJECT => the parameters are given * by an asn1 OID */ if ((eckey = EC_KEY_new()) == NULL) { EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE); goto ecerr; } group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object)); if (group == NULL) goto ecerr; EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(eckey, group) == 0) goto ecerr; EC_GROUP_free(group); } /* We have parameters now set private key */ if (!d2i_ECPrivateKey(&eckey, &p_tmp, pkeylen)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } /* calculate public key (if necessary) */ if (EC_KEY_get0_public_key(eckey) == NULL) { const BIGNUM *priv_key; const EC_GROUP *group; EC_POINT *pub_key; /* the public key was not included in the SEC1 private * key => calculate the public key */ group = EC_KEY_get0_group(eckey); pub_key = EC_POINT_new(group); if (pub_key == NULL) { EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } priv_key = EC_KEY_get0_private_key(eckey); if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } if (EC_KEY_set_public_key(eckey, pub_key) == 0) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } EC_POINT_free(pub_key); } EVP_PKEY_assign_EC_KEY(pkey, eckey); if (ctx) BN_CTX_free(ctx); break; ecerr: if (ctx) BN_CTX_free(ctx); if (eckey) EC_KEY_free(eckey); if (pkey) EVP_PKEY_free(pkey); return NULL; #endif default: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); if (!a->algorithm) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp); else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); ERR_add_error_data(2, "TYPE=", obj_tmp); EVP_PKEY_free (pkey); return NULL; } return pkey; }
static LUA_FUNCTION(openssl_pkey_new) { EVP_PKEY *pkey = NULL; const char* alg = "rsa"; if (lua_isnoneornil(L, 1) || lua_isstring(L, 1)) { alg = luaL_optstring(L, 1, alg); if (strcasecmp(alg, "rsa") == 0) { int bits = luaL_optint(L, 2, 1024); int e = luaL_optint(L, 3, 65537); RSA* rsa = RSA_new(); BIGNUM *E = BN_new(); BN_set_word(E, e); if (RSA_generate_key_ex(rsa, bits, E, NULL)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); } else RSA_free(rsa); BN_free(E); } else if (strcasecmp(alg, "dsa") == 0) { int bits = luaL_optint(L, 2, 1024); size_t seed_len = 0; const char* seed = luaL_optlstring(L, 3, NULL, &seed_len); DSA *dsa = DSA_new(); if (DSA_generate_parameters_ex(dsa, bits, (byte*)seed, seed_len, NULL, NULL, NULL) && DSA_generate_key(dsa)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_DSA(pkey, dsa); } else DSA_free(dsa); } else if (strcasecmp(alg, "dh") == 0) { int bits = luaL_optint(L, 2, 512); int generator = luaL_optint(L, 3, 2); DH* dh = DH_new(); if (DH_generate_parameters_ex(dh, bits, generator, NULL)) { if (DH_generate_key(dh)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_DH(pkey, dh); } else DH_free(dh); } else DH_free(dh); } #ifndef OPENSSL_NO_EC else if (strcasecmp(alg, "ec") == 0) { int ec_name = NID_undef; EC_KEY *ec = NULL; EC_GROUP *group = openssl_get_ec_group(L, 2, 3, 4); if (!group) luaL_error(L, "failed to get ec_group object"); ec = EC_KEY_new(); if (ec) { EC_KEY_set_group(ec, group); EC_GROUP_free(group); if (EC_KEY_generate_key(ec)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_EC_KEY(pkey, ec); } else EC_KEY_free(ec); } else EC_GROUP_free(group); } #endif else { luaL_error(L, "not support %s!!!!", alg); } } else if (lua_istable(L, 1)) { lua_getfield(L, 1, "alg"); alg = luaL_optstring(L, -1, alg); lua_pop(L, 1); if (strcasecmp(alg, "rsa") == 0) { pkey = EVP_PKEY_new(); if (pkey) { RSA *rsa = RSA_new(); if (rsa) { OPENSSL_PKEY_SET_BN(1, rsa, n); OPENSSL_PKEY_SET_BN(1, rsa, e); OPENSSL_PKEY_SET_BN(1, rsa, d); OPENSSL_PKEY_SET_BN(1, rsa, p); OPENSSL_PKEY_SET_BN(1, rsa, q); OPENSSL_PKEY_SET_BN(1, rsa, dmp1); OPENSSL_PKEY_SET_BN(1, rsa, dmq1); OPENSSL_PKEY_SET_BN(1, rsa, iqmp); if (rsa->n) { if (!EVP_PKEY_assign_RSA(pkey, rsa)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "dsa") == 0) { pkey = EVP_PKEY_new(); if (pkey) { DSA *dsa = DSA_new(); if (dsa) { OPENSSL_PKEY_SET_BN(-1, dsa, p); OPENSSL_PKEY_SET_BN(-1, dsa, q); OPENSSL_PKEY_SET_BN(-1, dsa, g); OPENSSL_PKEY_SET_BN(-1, dsa, priv_key); OPENSSL_PKEY_SET_BN(-1, dsa, pub_key); if (dsa->p && dsa->q && dsa->g) { if (!dsa->priv_key && !dsa->pub_key) { DSA_generate_key(dsa); } if (!EVP_PKEY_assign_DSA(pkey, dsa)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "dh") == 0) { pkey = EVP_PKEY_new(); if (pkey) { DH *dh = DH_new(); if (dh) { OPENSSL_PKEY_SET_BN(-1, dh, p); OPENSSL_PKEY_SET_BN(-1, dh, g); OPENSSL_PKEY_SET_BN(-1, dh, priv_key); OPENSSL_PKEY_SET_BN(-1, dh, pub_key); if (dh->p && dh->g) { if (!dh->pub_key) { DH_generate_key(dh); } if (!EVP_PKEY_assign_DH(pkey, dh)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "ec") == 0) { BIGNUM *d = NULL; BIGNUM *x = NULL; BIGNUM *y = NULL; BIGNUM *z = NULL; EC_GROUP *group = NULL; lua_getfield(L, -1, "ec_name"); lua_getfield(L, -2, "param_enc"); lua_getfield(L, -3, "conv_form"); group = openssl_get_ec_group(L, -3, -2, -1); lua_pop(L, 3); if (!group) { luaL_error(L, "get openssl.ec_group fail"); } EC_GET_FIELD(d); EC_GET_FIELD(x); EC_GET_FIELD(y); EC_GET_FIELD(z); pkey = EVP_PKEY_new(); if (pkey) { EC_KEY *ec = EC_KEY_new(); if (ec) { EC_KEY_set_group(ec, group); if (d) EC_KEY_set_private_key(ec, d); if (x != NULL && y != NULL) { EC_POINT *pnt = EC_POINT_new(group); if (z == NULL) EC_POINT_set_affine_coordinates_GFp(group, pnt, x, y, NULL); else EC_POINT_set_Jprojective_coordinates_GFp(group, pnt, x, y, z, NULL); EC_KEY_set_public_key(ec, pnt); } if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { EC_KEY_free(ec); EVP_PKEY_free(pkey); pkey = NULL; } if (d && !EC_KEY_check_key(ec)) { EC_KEY_generate_key_part(ec); } } } } } if (pkey) { PUSH_OBJECT(pkey, "openssl.evp_pkey"); return 1; } return 0; }
int ecparam_main(int argc, char **argv) { BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL; BIO *in = NULL, *out = NULL; EC_GROUP *group = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; char *curve_name = NULL, *inrand = NULL; char *infile = NULL, *outfile = NULL, *prog; unsigned char *buffer = NULL; OPTION_CHOICE o; int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0, ret = 1; int list_curves = 0, no_seed = 0, check = 0, new_form = 0; int text = 0, i, need_rand = 0, genkey = 0; prog = opt_init(argc, argv, ecparam_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(ecparam_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_TEXT: text = 1; break; case OPT_C: C = 1; break; case OPT_CHECK: check = 1; break; case OPT_LIST_CURVES: list_curves = 1; break; case OPT_NO_SEED: no_seed = 1; break; case OPT_NOOUT: noout = 1; break; case OPT_NAME: curve_name = opt_arg(); break; case OPT_CONV_FORM: if (!opt_pair(opt_arg(), forms, &new_form)) goto opthelp; form = new_form; new_form = 1; break; case OPT_PARAM_ENC: if (!opt_pair(opt_arg(), encodings, &asn1_flag)) goto opthelp; new_asn1_flag = 1; break; case OPT_GENKEY: genkey = need_rand = 1; break; case OPT_RAND: inrand = opt_arg(); need_rand = 1; break; case OPT_ENGINE: (void)setup_engine(opt_arg(), 0); break; } } argc = opt_num_rest(); argv = opt_rest(); in = bio_open_default(infile, RB(informat)); if (in == NULL) goto end; out = bio_open_default(outfile, WB(outformat)); if (out == NULL) goto end; if (list_curves) { EC_builtin_curve *curves = NULL; size_t crv_len = EC_get_builtin_curves(NULL, 0); size_t n; curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); if (!EC_get_builtin_curves(curves, crv_len)) { OPENSSL_free(curves); goto end; } for (n = 0; n < crv_len; n++) { const char *comment; const char *sname; comment = curves[n].comment; sname = OBJ_nid2sn(curves[n].nid); if (comment == NULL) comment = "CURVE DESCRIPTION NOT AVAILABLE"; if (sname == NULL) sname = ""; BIO_printf(out, " %-10s: ", sname); BIO_printf(out, "%s\n", comment); } OPENSSL_free(curves); ret = 0; goto end; } if (curve_name != NULL) { int nid; /* * workaround for the SECG curve names secp192r1 and secp256r1 (which * are the same as the curves prime192v1 and prime256v1 defined in * X9.62) */ if (strcmp(curve_name, "secp192r1") == 0) { BIO_printf(bio_err, "using curve name prime192v1 " "instead of secp192r1\n"); nid = NID_X9_62_prime192v1; } else if (strcmp(curve_name, "secp256r1") == 0) { BIO_printf(bio_err, "using curve name prime256v1 " "instead of secp256r1\n"); nid = NID_X9_62_prime256v1; } else nid = OBJ_sn2nid(curve_name); if (nid == 0) nid = EC_curve_nist2nid(curve_name); if (nid == 0) { BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); goto end; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); goto end; } EC_GROUP_set_asn1_flag(group, asn1_flag); EC_GROUP_set_point_conversion_form(group, form); } else if (informat == FORMAT_ASN1) group = d2i_ECPKParameters_bio(in, NULL); else group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); if (group == NULL) { BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); ERR_print_errors(bio_err); goto end; } if (new_form) EC_GROUP_set_point_conversion_form(group, form); if (new_asn1_flag) EC_GROUP_set_asn1_flag(group, asn1_flag); if (no_seed) { EC_GROUP_set_seed(group, NULL, 0); } if (text) { if (!ECPKParameters_print(out, group, 0)) goto end; } if (check) { if (group == NULL) BIO_printf(bio_err, "no elliptic curve parameters\n"); BIO_printf(bio_err, "checking elliptic curve parameters: "); if (!EC_GROUP_check(group, NULL)) { BIO_printf(bio_err, "failed\n"); ERR_print_errors(bio_err); } else BIO_printf(bio_err, "ok\n"); } if (C) { size_t buf_len = 0, tmp_len = 0; const EC_POINT *point; int is_prime, len = 0; const EC_METHOD *meth = EC_GROUP_method_of(group); if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL || (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL || (ec_order = BN_new()) == NULL || (ec_cofactor = BN_new()) == NULL) { perror("Can't allocate BN"); goto end; } is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); if (!is_prime) { BIO_printf(bio_err, "Can only handle X9.62 prime fields\n"); goto end; } if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, ec_b, NULL)) goto end; if ((point = EC_GROUP_get0_generator(group)) == NULL) goto end; if (!EC_POINT_point2bn(group, point, EC_GROUP_get_point_conversion_form(group), ec_gen, NULL)) goto end; if (!EC_GROUP_get_order(group, ec_order, NULL)) goto end; if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) goto end; if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) goto end; len = BN_num_bits(ec_order); if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len) buf_len = tmp_len; buffer = app_malloc(buf_len, "BN buffer"); BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len); print_bignum_var(out, ec_p, "ec_p", len, buffer); print_bignum_var(out, ec_a, "ec_a", len, buffer); print_bignum_var(out, ec_b, "ec_b", len, buffer); print_bignum_var(out, ec_gen, "ec_gen", len, buffer); print_bignum_var(out, ec_order, "ec_order", len, buffer); print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer); BIO_printf(out, " int ok = 0;\n" " EC_GROUP *group = NULL;\n" " EC_POINT *point = NULL;\n" " BIGNUM *tmp_1 = NULL;\n" " BIGNUM *tmp_2 = NULL;\n" " BIGNUM *tmp_3 = NULL;\n" "\n"); BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof (ec_p_%d), NULL)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof (ec_a_%d), NULL)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof (ec_b_%d), NULL)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n" " goto err;\n" "\n"); BIO_printf(out, " /* build generator */\n"); BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof (ec_gen_%d), tmp_1)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n"); BIO_printf(out, " if (point == NULL)\n" " goto err;\n"); BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof (ec_order_%d), tmp_2)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof (ec_cofactor_%d), tmp_3)) == NULL)\n" " goto err;\n", len, len); BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n" " goto err;\n" "ok = 1;" "\n"); BIO_printf(out, "err:\n" " BN_free(tmp_1);\n" " BN_free(tmp_2);\n" " BN_free(tmp_3);\n" " EC_POINT_free(point);\n" " if (!ok) {\n" " EC_GROUP_free(group);\n" " return NULL;\n" " }\n" " return (group);\n" "}\n"); } if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_ECPKParameters_bio(out, group); else i = PEM_write_bio_ECPKParameters(out, group); if (!i) { BIO_printf(bio_err, "unable to write elliptic " "curve parameters\n"); ERR_print_errors(bio_err); goto end; } } if (need_rand) { app_RAND_load_file(NULL, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err, "%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } if (genkey) { EC_KEY *eckey = EC_KEY_new(); if (eckey == NULL) goto end; assert(need_rand); if (EC_KEY_set_group(eckey, group) == 0) goto end; if (!EC_KEY_generate_key(eckey)) { EC_KEY_free(eckey); goto end; } if (outformat == FORMAT_ASN1) i = i2d_ECPrivateKey_bio(out, eckey); else i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL); EC_KEY_free(eckey); } if (need_rand) app_RAND_write_file(NULL); ret = 0; end: BN_free(ec_p); BN_free(ec_a); BN_free(ec_b); BN_free(ec_gen); BN_free(ec_order); BN_free(ec_cofactor); OPENSSL_free(buffer); BIO_free(in); BIO_free_all(out); EC_GROUP_free(group); return (ret); }
EC_KEY * ECKey_From(const cn_cbor * pKey, int * cbGroup, cose_errback * perr) { EC_KEY * pNewKey = EC_KEY_new(); byte rgbKey[512+1]; const cn_cbor * p; int nidGroup = -1; EC_POINT * pPoint = NULL; p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Curve); CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER); switch (p->v.sint) { case 1: // P-256 nidGroup = NID_X9_62_prime256v1; *cbGroup = 256 / 8; break; case 2: // P-384 nidGroup = NID_secp384r1; *cbGroup = 384 / 8; break; case 3: // P-521 nidGroup = NID_secp521r1; *cbGroup = (521 + 7) / 8; break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); } EC_GROUP * ecgroup = EC_GROUP_new_by_curve_name(nidGroup); EC_KEY_set_group(pNewKey, ecgroup); rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED; p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X); if (p == NULL) return NULL; if (p->type != CN_CBOR_BYTES) return NULL; memcpy(rgbKey+1, p->v.str, p->length); p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y); if (p == NULL) return NULL; if (p->type != CN_CBOR_BYTES) return NULL; memcpy(rgbKey + p->length+1, p->v.str, p->length); pPoint = EC_POINT_new(ecgroup); EC_POINT_oct2point(ecgroup, pPoint, rgbKey, p->length * 2 + 1, NULL); EC_KEY_set_public_key(pNewKey, pPoint); p = cn_cbor_mapget_int(pKey, COSE_Key_EC_d); if (p != NULL) { BIGNUM * pbn; pbn = BN_bin2bn(p->v.bytes, (int) p->length, NULL); EC_KEY_set_private_key(pNewKey, pbn); } return pNewKey; errorReturn: return NULL; }
CECKey::CECKey() { pkey = EC_KEY_new(); assert(pkey != NULL); int result = EC_KEY_set_group(pkey, ecgroup_order::get()); assert(result); }
PKI_EC_KEY * _pki_pkcs11_ecdsakey_new(PKI_KEYPARAMS * kp, URL * url, PKCS11_HANDLER * lib, void * driver) { PKI_EC_KEY * ret = NULL; CK_OBJECT_HANDLE *handler_pubkey = NULL; CK_OBJECT_HANDLE *handler_privkey = NULL; CK_ATTRIBUTE privTemp[32]; CK_ATTRIBUTE pubTemp[32]; CK_RV rv; CK_ULONG i = 0; CK_ULONG n = 0; CK_ULONG bits = 0; size_t label_len = 0; unsigned char *data = NULL; CK_BYTE *esp = NULL; CK_ULONG size = 0; BIGNUM *bn = NULL; BIGNUM *id_num = NULL; CK_MECHANISM * EC_MECH_PTR = NULL; int idx = 0; char *id = NULL; int id_len = 8; if ( !url || !url->addr ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return ( NULL ); } label_len = strlen( url->addr ); /* Check the min size for the key */ if ( kp ) { if( kp->bits < PKI_EC_KEY_MIN_SIZE ) { PKI_ERROR(PKI_ERR_X509_KEYPAIR_SIZE_SHORT, NULL); }; } else { bits = PKI_EC_KEY_DEFAULT_SIZE; } // Look for a supported key generation mechanism for (idx = 0; idx < EC_MECH_LIST_SIZE; idx++) { // Checks if the mechanism is supported if (HSM_PKCS11_check_mechanism(lib, EC_MECH_LIST[idx].mechanism) == PKI_OK) { // Set the pointer to the supported mechanism EC_MECH_PTR = &EC_MECH_LIST[idx]; // Debugging Information PKI_DEBUG("Found EC KEY GEN MECHANISM 0x%8.8X", EC_MECH_LIST[idx].mechanism); // Breaks out of the loop break; } else { // Let's provide debug information for not-supported mechs PKI_DEBUG("EC KEY GEN MECHANISM 0x%8.8X not supported", RSA_MECH_LIST[idx].mechanism); } } // If no key gen algors are supported, abort if (EC_MECH_PTR == NULL) { PKI_ERROR(PKI_ERR_HSM_KEYPAIR_GENERATE, "No KeyGen Mechanisms supported!"); return NULL; } PKI_DEBUG("BITS FOR KEY GENERATION %lu (def: %lu)", bits, PKI_EC_KEY_DEFAULT_SIZE); if ( kp && kp->rsa.exponent > 3) { // TO be Implemented } else { if( BN_hex2bn(&bn, "10001") == 0 ) { PKI_log_debug("ERROR, can not convert 10001 to BIGNUM"); return ( NULL ); } } if( url->path != NULL ) { if((BN_hex2bn(&id_num, url->path )) == 0 ) { PKI_log_debug("ERROR, can not convert %s to BIGNUM", url->path ); return ( NULL ); } if((id_len = BN_num_bytes(id_num)) < 0 ) { if ( bn ) BN_free ( bn ); if ( id_num ) BN_free ( id_num ); return ( NULL ); } id = PKI_Malloc ( (size_t ) id_len ); BN_bn2bin( id_num, (unsigned char *) id ); } else { id_len = 10; if((id = PKI_Malloc ( (size_t) id_len )) == NULL ) { if ( bn ) BN_free ( bn ); return ( NULL ); } if( RAND_bytes( (unsigned char *) id, id_len) == 0 ) { PKI_ERROR(PKI_ERR_X509_KEYPAIR_GENERATION, "Can not generate RAND bytes"); if( bn ) BN_free ( bn ); return ( NULL ); } } PKI_DEBUG("Setting the Bits to %lu", bits); /* Setting Attributes for the public Key Template */ n = 0; //HSM_PKCS11_set_attr_int( CKA_CLASS, CKO_PUBLIC_KEY, &pubTemp[n++]); //HSM_PKCS11_set_attr_int( CKA_KEY_TYPE, CKK_RSA, &pubTemp[n++]); HSM_PKCS11_set_attr_int( CKA_MODULUS_BITS, bits, &pubTemp[n++]); HSM_PKCS11_set_attr_bool( CKA_TOKEN, CK_TRUE, &pubTemp[n++]); HSM_PKCS11_set_attr_bool( CKA_ENCRYPT, CK_TRUE, &pubTemp[n++]); HSM_PKCS11_set_attr_bool( CKA_VERIFY, CK_TRUE, &pubTemp[n++]); HSM_PKCS11_set_attr_bool( CKA_WRAP, CK_TRUE, &pubTemp[n++]); HSM_PKCS11_set_attr_bn(CKA_PUBLIC_EXPONENT, bn, &pubTemp[n++]); HSM_PKCS11_set_attr_sn(CKA_LABEL, url->addr, label_len, &pubTemp[n++]); HSM_PKCS11_set_attr_sn(CKA_ID, id, (size_t) id_len, &pubTemp[n++]); /* Setting Attributes for the private Key Template */ i = 0; //HSM_PKCS11_set_attr_int( CKA_CLASS, CKO_PRIVATE_KEY, &privTemp[i++]); //HSM_PKCS11_set_attr_int( CKA_KEY_TYPE, CKK_RSA, &privTemp[i++]); //HSM_PKCS11_set_attr_int( CKA_MODULUS_BITS, bits, &privTemp[i++]); HSM_PKCS11_set_attr_bool( CKA_TOKEN, CK_TRUE, &privTemp[i++]); HSM_PKCS11_set_attr_bool( CKA_PRIVATE, CK_TRUE, &privTemp[i++]); HSM_PKCS11_set_attr_bool( CKA_SENSITIVE, CK_TRUE, &privTemp[i++]); HSM_PKCS11_set_attr_bool( CKA_DECRYPT, CK_TRUE, &privTemp[i++]); HSM_PKCS11_set_attr_bool( CKA_SIGN, CK_TRUE, &privTemp[i++]); // HSM_PKCS11_set_attr_bool( CKA_NEVER_EXTRACTABLE, CK_TRUE, // &privTemp[i++]); // HSM_PKCS11_set_attr_bool( CKA_EXTRACTABLE, CK_FALSE, &privTemp[i++]); HSM_PKCS11_set_attr_bool( CKA_UNWRAP, CK_TRUE, &privTemp[i++]); // HSM_PKCS11_set_attr_bn(CKA_PUBLIC_EXPONENT, bn, &privTemp[i++]); HSM_PKCS11_set_attr_sn(CKA_LABEL, url->addr, label_len, &privTemp[i++]); HSM_PKCS11_set_attr_sn(CKA_ID, id, (size_t) id_len, &privTemp[i++]); /* Allocate the handlers for pub and priv keys */ handler_pubkey = (CK_OBJECT_HANDLE *) PKI_Malloc ( sizeof( CK_OBJECT_HANDLE )); handler_privkey = (CK_OBJECT_HANDLE *) PKI_Malloc ( sizeof( CK_OBJECT_HANDLE )); if( !handler_pubkey || !handler_privkey ) { if ( bn ) BN_free ( bn ); if ( esp ) PKI_Free ( esp ); return ( NULL ); } PKI_log_debug("Generating a new Key ... "); rv = lib->callbacks->C_GenerateKeyPair ( lib->session, EC_MECH_PTR, pubTemp, n, privTemp, i, handler_pubkey, handler_privkey); if( rv != CKR_OK ) { if ( rv == CKR_MECHANISM_INVALID ) { PKI_ERROR(PKI_ERR_HSM_SET_ALGOR, "EC Algorithm is not supported by the Token"); } else { PKI_log_debug ("Failed with code 0x%8.8X", rv ); } if ( bn ) BN_free ( bn ); if ( esp ) PKI_Free ( esp ); return ( NULL ); } /* Clean up the Memory we are not using anymore */ if ( bn ) BN_free ( bn ); if ( esp ) PKI_Free ( esp ); /* Generate a new RSA container */ if((ret = EC_KEY_new()) == NULL ) goto err; if( HSM_PKCS11_get_attribute(handler_pubkey, &lib->session, CKA_PUBLIC_EXPONENT, (void **) &data, &size, lib) != PKI_OK ) { goto err; } EC_KEY_set_private_key(ret, BN_bin2bn( data, (int) size, NULL)); PKI_Free(data); data = NULL; if( HSM_PKCS11_get_attribute(handler_pubkey, &lib->session, CKA_MODULUS, (void **) &data, &size, lib) != PKI_OK ) { goto err; } EC_KEY_set_public_key(ret, (const EC_POINT *) NULL); PKI_Free ( data ); data = NULL; /* ECDSA_set_method(ret, HSM_PKCS11_get_ecdsa_method()); #ifdef RSA_FLAG_SIGN_VER # if OPENSSL_VERSION_NUMBER >= 0x1010000fL RSA_set_flags( ret, RSA_FLAG_SIGN_VER); # else ret->flags |= RSA_FLAG_SIGN_VER; # endif #endif // Push the priv and pub key handlers to the rsa->ex_data EC_KEY_set_ex_data( ret, KEYPAIR_DRIVER_HANDLER_IDX, driver ); EC_KEY_set_ex_data( ret, KEYPAIR_PRIVKEY_HANDLER_IDX, handler_privkey ); EC_KEY_set_ex_data( ret, KEYPAIR_PUBKEY_HANDLER_IDX, handler_pubkey ); // Cleanup the memory for Templates HSM_PKCS11_clean_template ( pubTemp, (int) n ); HSM_PKCS11_clean_template ( privTemp, (int) i ); */ // Let's return the RSA_KEY infrastructure return (ret); err: if (ret) EC_KEY_free(ret); if ( handler_pubkey ) { if((rv = lib->callbacks->C_DestroyObject( lib->session, *handler_pubkey )) != CKR_OK ) { PKI_log_debug ("Failed to delete pubkey object"); } PKI_Free(handler_pubkey); } if( handler_privkey ) { if((rv = lib->callbacks->C_DestroyObject(lib->session, *handler_privkey)) != CKR_OK) { PKI_log_debug ("Failed to delete privkey object"); } PKI_Free(handler_privkey); } return NULL; }
int main(int argc, const char *argv[]) { int r; int ok = 0; char *prog = "ecc"; // libpopt var poptContext popt_ctx; const char **rest; int command = 0; char *curve_name = "secp192k1"; int point_compressed = 0; point_conversion_form_t point_form; struct poptOption options[] = { {"curve-name", 'c', POPT_ARG_STRING, &curve_name, 0, "elliptic curve name", "NAME"}, {"point-compressed", 'z', POPT_ARG_NONE, &point_compressed, 0, "point format, compress or uncompress", NULL}, {"print-curve", 'p', POPT_ARG_VAL, &command, ECC_PRINT, "print elliptic curve parameters", NULL}, {"random-private-key", 0, POPT_ARG_VAL, &command, ECC_RAND_SKEY, "random generate a private key\n", NULL}, {"random-keypair", 0, POPT_ARG_VAL, &command, ECC_RAND_KEYPAIR, "generate a random key pair\n", NULL}, {"check-point", 'e', POPT_ARG_VAL, &command, ECC_CHECK_POINT, "check if point is valid\n", NULL}, {"point-add", 'a', POPT_ARG_VAL, &command, ECC_ADD, "elliptic curve point addition", NULL}, {"point-double", 'b', POPT_ARG_VAL, &command, ECC_DOUBLE, "elliptic curve point double", NULL}, {"point-mul", 'x', POPT_ARG_VAL, &command, ECC_MUL, "k*G", NULL}, {"point-mul-generator", 'X', POPT_ARG_VAL, &command, ECC_MUL_G, "elliptic curve point scalar multiply", NULL}, {"point-invert", 'i', POPT_ARG_VAL, &command, ECC_INVERT, "elliptic curve point inverse", NULL}, {"ecdsa-sign", 's', POPT_ARG_VAL, &command, ECC_SIGN, "ecdsa sign", NULL}, {"ecdsa-verify", 'v', POPT_ARG_VAL, &command, ECC_VERIFY, "ecdsa verify", NULL}, POPT_AUTOHELP POPT_TABLEEND }; // openssl var EC_GROUP *ec_group = NULL; EC_POINT *P = NULL; EC_POINT *Q = NULL; EC_POINT *R = NULL; BIGNUM *k = BN_new(); BN_CTX *bn_ctx = BN_CTX_new(); // argument parsing popt_ctx = poptGetContext(argv[0], argc, argv, options, 0); if ((r = poptGetNextOpt(popt_ctx)) < -1) { fprintf(stderr, "%s: bad argument %s: %s\n", argv[0], poptBadOption(popt_ctx, POPT_BADOPTION_NOALIAS), poptStrerror(r)); goto exit; } rest = poptGetArgs(popt_ctx); // check arguments ec_group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve_name)); if (ec_group == NULL) { fprintf(stderr, "%s: unknown curve name\n", prog); goto exit; } P = EC_POINT_new(ec_group); Q = EC_POINT_new(ec_group); R = EC_POINT_new(ec_group); point_form = point_compressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED; switch (command) { case ECC_PRINT: { BIGNUM *p = BN_new(); BIGNUM *a = BN_new(); BIGNUM *b = BN_new(); char *generator; BIGNUM *order = BN_new(); BIGNUM *cofactor = BN_new(); EC_GROUP_get_curve_GFp(ec_group, p, a, b, bn_ctx); generator = EC_POINT_point2hex(ec_group, EC_GROUP_get0_generator(ec_group), point_form, bn_ctx); EC_GROUP_get_order(ec_group, order, bn_ctx); EC_GROUP_get_cofactor(ec_group, cofactor, bn_ctx); fprintf(stdout, "Name : %s\n", OBJ_nid2sn(EC_GROUP_get_curve_name(ec_group))); fprintf(stdout, "FieldType : %s\n", "PrimeField"); fprintf(stdout, "Prime : %s\n", BN_bn2hex(p)); fprintf(stdout, "A : %s\n", BN_bn2hex(a)); fprintf(stdout, "B : %s\n", BN_bn2hex(b)); fprintf(stdout, "Generator : %s\n", generator); fprintf(stdout, "Order : %s\n", BN_bn2hex(order)); fprintf(stdout, "Cofactor : %s\n", BN_bn2hex(cofactor)); BN_free(p); BN_free(a); BN_free(b); BN_free(order); BN_free(cofactor); break; } case ECC_CHECK_POINT: { if (!rest) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (!rest[0]) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (EC_POINT_hex2point(ec_group, rest[0], P, bn_ctx)) fprintf(stdout, "ture\n"); else fprintf(stdout, "false\n"); break; } case ECC_RAND_SKEY: { EC_KEY *ec_key = EC_KEY_new(); EC_KEY_set_group(ec_key, ec_group); EC_KEY_generate_key(ec_key); fprintf(stdout, "%s\n", BN_bn2hex(EC_KEY_get0_private_key(ec_key))); EC_KEY_free(ec_key); break; } case ECC_RAND_KEYPAIR: { EC_KEY *ec_key = EC_KEY_new(); EC_KEY_set_group(ec_key, ec_group); EC_KEY_generate_key(ec_key); fprintf(stdout, "%s\n", BN_bn2hex(EC_KEY_get0_private_key(ec_key))); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, EC_KEY_get0_public_key(ec_key), point_form, bn_ctx)); EC_KEY_free(ec_key); break; } case ECC_ADD: { if (!rest) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (!rest[0] || !rest[1]) { fprintf(stderr, "%s: short of point\n", prog); goto exit; } if (!EC_POINT_hex2point(ec_group, rest[1], P, bn_ctx)) { fprintf(stderr, "%s: first point invalid\n", prog); goto exit; } if (!EC_POINT_hex2point(ec_group, rest[1], Q, bn_ctx)) { fprintf(stderr, "%s: second point invalid\n", prog); goto exit; } EC_POINT_add(ec_group, R, P, Q, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } case ECC_DOUBLE: { EC_POINT_dbl(ec_group, R, P, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } case ECC_MUL: { BIGNUM *order = NULL; if (!BN_hex2bn(&k, rest[0])) { fprintf(stderr, "%s: integer invalid\n", prog); goto exit; } order = BN_new(); EC_GROUP_get_order(ec_group, order, bn_ctx); if (BN_cmp(k, order) >= 0) { fprintf(stderr, "%s: integer value invalid\n", prog); BN_free(order); goto exit; } BN_free(order); if (!EC_POINT_hex2point(ec_group, rest[1], P, bn_ctx)) { fprintf(stderr, "%s: point invalid\n", prog); goto exit; } EC_POINT_mul(ec_group, R, k, P, NULL, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } case ECC_MUL_G: { BIGNUM *order = NULL; if (!BN_hex2bn(&k, rest[0])) { fprintf(stderr, "%s: integer format invalid\n", prog); goto exit; } order = BN_new(); EC_GROUP_get_order(ec_group, order, bn_ctx); if (BN_cmp(k, order) >= 0) { fprintf(stderr, "%s: integer value invalid\n", prog); BN_free(order); goto exit; } BN_free(order); EC_POINT_mul(ec_group, R, k, EC_GROUP_get0_generator(ec_group), NULL, bn_ctx); fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx)); break; } default: fprintf(stderr, "%s: command is required\n", prog); break; } ok = 1; exit: if (ec_group) EC_GROUP_free(ec_group); if (P) EC_POINT_free(P); if (k) BN_free(k); if (bn_ctx) BN_CTX_free(bn_ctx); return ok ? 0 : -1; }
static int ecdsa_verify_signature(hx509_context context, const struct signature_alg *sig_alg, const Certificate *signer, const AlgorithmIdentifier *alg, const heim_octet_string *data, const heim_octet_string *sig) { const AlgorithmIdentifier *digest_alg; const SubjectPublicKeyInfo *spi; heim_octet_string digest; int ret; EC_KEY *key = NULL; int groupnid; EC_GROUP *group; const unsigned char *p; long len; digest_alg = sig_alg->digest_alg; ret = _hx509_create_signature(context, NULL, digest_alg, data, NULL, &digest); if (ret) return ret; /* set up EC KEY */ spi = &signer->tbsCertificate.subjectPublicKeyInfo; if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0) return HX509_CRYPTO_SIG_INVALID_FORMAT; /* * Find the group id */ ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid); if (ret) { der_free_octet_string(&digest); return ret; } /* * Create group, key, parse key */ key = EC_KEY_new(); group = EC_GROUP_new_by_curve_name(groupnid); EC_KEY_set_group(key, group); EC_GROUP_free(group); p = spi->subjectPublicKey.data; len = spi->subjectPublicKey.length / 8; if (o2i_ECPublicKey(&key, &p, len) == NULL) { EC_KEY_free(key); return HX509_CRYPTO_SIG_INVALID_FORMAT; } ret = ECDSA_verify(-1, digest.data, digest.length, sig->data, sig->length, key); der_free_octet_string(&digest); EC_KEY_free(key); if (ret != 1) { ret = HX509_CRYPTO_SIG_INVALID_FORMAT; return ret; } return 0; }
int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key,size_t key_len) { GOST_KEY_TRANSPORT *gkt=NULL; EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); struct gost_pmeth_data *data = (gost_pmeth_data*)EVP_PKEY_CTX_get_data(pctx); const struct gost_cipher_info *param=get_encryption_params(NULL); unsigned char ukm[8], shared_key[32], crypted_key[44]; int ret=0; int key_is_ephemeral=1; gost_ctx cctx; EVP_PKEY *sec_key=EVP_PKEY_CTX_get0_peerkey(pctx); if (data->shared_ukm) { TINYCLR_SSL_MEMCPY(ukm, data->shared_ukm,8); } else if (out) { if (RAND_bytes(ukm,8)<=0) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); return 0; } } /* Check for private key in the peer_key of context */ if (sec_key) { key_is_ephemeral=0; if (!gost_get0_priv_key(sec_key)) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { key_is_ephemeral=1; if (out) { sec_key = EVP_PKEY_new(); EVP_PKEY_assign(sec_key,EVP_PKEY_base_id(pubk),EC_KEY_new()); EVP_PKEY_copy_parameters(sec_key,pubk); if (!gost2001_keygen((EC_KEY*)EVP_PKEY_get0(sec_key))) { goto err; } } } if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param= gost_cipher_list+1; } if (out) { VKO_compute_key(shared_key,32,EC_KEY_get0_public_key((const EC_KEY*)EVP_PKEY_get0(pubk)),(EC_KEY*)EVP_PKEY_get0(sec_key),ukm); gost_init(&cctx,param->sblock); keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { goto err; } if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm,8)) { goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { goto err; } if (key_is_ephemeral) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?sec_key:pubk)) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key); if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1; GOST_KEY_TRANSPORT_free(gkt); return ret; err: if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key); GOST_KEY_TRANSPORT_free(gkt); return -1; }
/* * verify EC signature on JWT */ static apr_byte_t apr_jws_verify_ec(apr_pool_t *pool, apr_jwt_t *jwt, apr_jwk_t *jwk, apr_jwt_error_t *err) { int nid = apr_jws_ec_alg_to_curve(jwt->header.alg); if (nid == -1) { apr_jwt_error(err, "no OpenSSL Elliptic Curve identifier found for algorithm \"%s\"", jwt->header.alg); return FALSE; } EC_GROUP *curve = EC_GROUP_new_by_curve_name(nid); if (curve == NULL) { apr_jwt_error(err, "no OpenSSL Elliptic Curve found for algorithm \"%s\"", jwt->header.alg); return FALSE; } apr_byte_t rc = FALSE; /* get the OpenSSL digest function */ const EVP_MD *digest = NULL; if ((digest = apr_jws_crypto_alg_to_evp(pool, jwt->header.alg, err)) == NULL) return FALSE; EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); EC_KEY * pubkey = EC_KEY_new(); EC_KEY_set_group(pubkey, curve); BIGNUM * x = BN_new(); BIGNUM * y = BN_new(); BN_bin2bn(jwk->key.ec->x, jwk->key.ec->x_len, x); BN_bin2bn(jwk->key.ec->y, jwk->key.ec->y_len, y); if (!EC_KEY_set_public_key_affine_coordinates(pubkey, x, y)) { apr_jwt_error_openssl(err, "EC_KEY_set_public_key_affine_coordinates"); return FALSE; } EVP_PKEY* pEcKey = EVP_PKEY_new(); if (!EVP_PKEY_assign_EC_KEY(pEcKey, pubkey)) { pEcKey = NULL; apr_jwt_error_openssl(err, "EVP_PKEY_assign_EC_KEY"); goto end; } ctx.pctx = EVP_PKEY_CTX_new(pEcKey, NULL); if (!EVP_PKEY_verify_init(ctx.pctx)) { apr_jwt_error_openssl(err, "EVP_PKEY_verify_init"); goto end; } if (!EVP_VerifyInit_ex(&ctx, digest, NULL)) { apr_jwt_error_openssl(err, "EVP_VerifyInit_ex"); goto end; } if (!EVP_VerifyUpdate(&ctx, jwt->message, strlen(jwt->message))) { apr_jwt_error_openssl(err, "EVP_VerifyUpdate"); goto end; } if (!EVP_VerifyFinal(&ctx, (const unsigned char *) jwt->signature.bytes, jwt->signature.length, pEcKey)) { apr_jwt_error_openssl(err, "wrong key? EVP_VerifyFinal"); goto end; } rc = TRUE; end: if (pEcKey) { EVP_PKEY_free(pEcKey); } else if (pubkey) { EC_KEY_free(pubkey); } EVP_MD_CTX_cleanup(&ctx); return rc; }
int ecparam_main(int argc, char **argv) { EC_GROUP *group = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; int new_form = 0; int asn1_flag = OPENSSL_EC_NAMED_CURVE; int new_asn1_flag = 0; char *curve_name = NULL, *inrand = NULL; int list_curves = 0, no_seed = 0, check = 0, badops = 0, text = 0, i, genkey = 0; char *infile = NULL, *outfile = NULL, *prog; BIO *in = NULL, *out = NULL; int informat, outformat, noout = 0, C = 0, ret = 1; char *engine = NULL; BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL, *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; unsigned char *buffer = NULL; signal(SIGPIPE, SIG_IGN); if (bio_err == NULL) if ((bio_err = BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; informat = FORMAT_PEM; outformat = FORMAT_PEM; prog = argv[0]; argc--; argv++; while (argc >= 1) { if (strcmp(*argv, "-inform") == 0) { if (--argc < 1) goto bad; informat = str2fmt(*(++argv)); } else if (strcmp(*argv, "-outform") == 0) { if (--argc < 1) goto bad; outformat = str2fmt(*(++argv)); } else if (strcmp(*argv, "-in") == 0) { if (--argc < 1) goto bad; infile = *(++argv); } else if (strcmp(*argv, "-out") == 0) { if (--argc < 1) goto bad; outfile = *(++argv); } else if (strcmp(*argv, "-text") == 0) text = 1; else if (strcmp(*argv, "-C") == 0) C = 1; else if (strcmp(*argv, "-check") == 0) check = 1; else if (strcmp(*argv, "-name") == 0) { if (--argc < 1) goto bad; curve_name = *(++argv); } else if (strcmp(*argv, "-list_curves") == 0) list_curves = 1; else if (strcmp(*argv, "-conv_form") == 0) { if (--argc < 1) goto bad; ++argv; new_form = 1; if (strcmp(*argv, "compressed") == 0) form = POINT_CONVERSION_COMPRESSED; else if (strcmp(*argv, "uncompressed") == 0) form = POINT_CONVERSION_UNCOMPRESSED; else if (strcmp(*argv, "hybrid") == 0) form = POINT_CONVERSION_HYBRID; else goto bad; } else if (strcmp(*argv, "-param_enc") == 0) { if (--argc < 1) goto bad; ++argv; new_asn1_flag = 1; if (strcmp(*argv, "named_curve") == 0) asn1_flag = OPENSSL_EC_NAMED_CURVE; else if (strcmp(*argv, "explicit") == 0) asn1_flag = 0; else goto bad; } else if (strcmp(*argv, "-no_seed") == 0) no_seed = 1; else if (strcmp(*argv, "-noout") == 0) noout = 1; else if (strcmp(*argv, "-genkey") == 0) { genkey = 1; } else if (strcmp(*argv, "-rand") == 0) { if (--argc < 1) goto bad; inrand = *(++argv); } else if (strcmp(*argv, "-engine") == 0) { if (--argc < 1) goto bad; engine = *(++argv); } else { BIO_printf(bio_err, "unknown option %s\n", *argv); badops = 1; break; } argc--; argv++; } if (badops) { bad: BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); BIO_printf(bio_err, "where options are\n"); BIO_printf(bio_err, " -inform arg input format - " "default PEM (DER or PEM)\n"); BIO_printf(bio_err, " -outform arg output format - " "default PEM\n"); BIO_printf(bio_err, " -in arg input file - " "default stdin\n"); BIO_printf(bio_err, " -out arg output file - " "default stdout\n"); BIO_printf(bio_err, " -noout do not print the " "ec parameter\n"); BIO_printf(bio_err, " -text print the ec " "parameters in text form\n"); BIO_printf(bio_err, " -check validate the ec " "parameters\n"); BIO_printf(bio_err, " -C print a 'C' " "function creating the parameters\n"); BIO_printf(bio_err, " -name arg use the " "ec parameters with 'short name' name\n"); BIO_printf(bio_err, " -list_curves prints a list of " "all currently available curve 'short names'\n"); BIO_printf(bio_err, " -conv_form arg specifies the " "point conversion form \n"); BIO_printf(bio_err, " possible values:" " compressed\n"); BIO_printf(bio_err, " " " uncompressed (default)\n"); BIO_printf(bio_err, " " " hybrid\n"); BIO_printf(bio_err, " -param_enc arg specifies the way" " the ec parameters are encoded\n"); BIO_printf(bio_err, " in the asn1 der " "encoding\n"); BIO_printf(bio_err, " possible values:" " named_curve (default)\n"); BIO_printf(bio_err, " " " explicit\n"); BIO_printf(bio_err, " -no_seed if 'explicit'" " parameters are chosen do not" " use the seed\n"); BIO_printf(bio_err, " -genkey generate ec" " key\n"); BIO_printf(bio_err, " -rand file files to use for" " random number input\n"); BIO_printf(bio_err, " -engine e use engine e, " "possibly a hardware device\n"); goto end; } ERR_load_crypto_strings(); in = BIO_new(BIO_s_file()); out = BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in, stdin, BIO_NOCLOSE); else { if (BIO_read_filename(in, infile) <= 0) { perror(infile); goto end; } } if (outfile == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); } else { if (BIO_write_filename(out, outfile) <= 0) { perror(outfile); goto end; } } #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif if (list_curves) { EC_builtin_curve *curves = NULL; size_t crv_len = 0; size_t n = 0; crv_len = EC_get_builtin_curves(NULL, 0); curves = malloc((int) (sizeof(EC_builtin_curve) * crv_len)); if (curves == NULL) goto end; if (!EC_get_builtin_curves(curves, crv_len)) { free(curves); goto end; } for (n = 0; n < crv_len; n++) { const char *comment; const char *sname; comment = curves[n].comment; sname = OBJ_nid2sn(curves[n].nid); if (comment == NULL) comment = "CURVE DESCRIPTION NOT AVAILABLE"; if (sname == NULL) sname = ""; BIO_printf(out, " %-10s: ", sname); BIO_printf(out, "%s\n", comment); } free(curves); ret = 0; goto end; } if (curve_name != NULL) { int nid; /* * workaround for the SECG curve names secp192r1 and * secp256r1 (which are the same as the curves prime192v1 and * prime256v1 defined in X9.62) */ if (!strcmp(curve_name, "secp192r1")) { BIO_printf(bio_err, "using curve name prime192v1 " "instead of secp192r1\n"); nid = NID_X9_62_prime192v1; } else if (!strcmp(curve_name, "secp256r1")) { BIO_printf(bio_err, "using curve name prime256v1 " "instead of secp256r1\n"); nid = NID_X9_62_prime256v1; } else nid = OBJ_sn2nid(curve_name); if (nid == 0) { BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); goto end; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); goto end; } EC_GROUP_set_asn1_flag(group, asn1_flag); EC_GROUP_set_point_conversion_form(group, form); } else if (informat == FORMAT_ASN1) { group = d2i_ECPKParameters_bio(in, NULL); } else if (informat == FORMAT_PEM) { group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); } else { BIO_printf(bio_err, "bad input format specified\n"); goto end; } if (group == NULL) { BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); ERR_print_errors(bio_err); goto end; } if (new_form) EC_GROUP_set_point_conversion_form(group, form); if (new_asn1_flag) EC_GROUP_set_asn1_flag(group, asn1_flag); if (no_seed) { EC_GROUP_set_seed(group, NULL, 0); } if (text) { if (!ECPKParameters_print(out, group, 0)) goto end; } if (check) { if (group == NULL) BIO_printf(bio_err, "no elliptic curve parameters\n"); BIO_printf(bio_err, "checking elliptic curve parameters: "); if (!EC_GROUP_check(group, NULL)) { BIO_printf(bio_err, "failed\n"); ERR_print_errors(bio_err); } else BIO_printf(bio_err, "ok\n"); } if (C) { size_t buf_len = 0, tmp_len = 0; const EC_POINT *point; int is_prime, len = 0; const EC_METHOD *meth = EC_GROUP_method_of(group); if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL || (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL || (ec_order = BN_new()) == NULL || (ec_cofactor = BN_new()) == NULL) { perror("malloc"); goto end; } is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); if (is_prime) { if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, ec_b, NULL)) goto end; } else { /* TODO */ goto end; } if ((point = EC_GROUP_get0_generator(group)) == NULL) goto end; if (!EC_POINT_point2bn(group, point, EC_GROUP_get_point_conversion_form(group), ec_gen, NULL)) goto end; if (!EC_GROUP_get_order(group, ec_order, NULL)) goto end; if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) goto end; if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) goto end; len = BN_num_bits(ec_order); if ((tmp_len = (size_t) BN_num_bytes(ec_p)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_a)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_b)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_gen)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_order)) > buf_len) buf_len = tmp_len; if ((tmp_len = (size_t) BN_num_bytes(ec_cofactor)) > buf_len) buf_len = tmp_len; buffer = (unsigned char *) malloc(buf_len); if (buffer == NULL) { perror("malloc"); goto end; } ecparam_print_var(out, ec_p, "ec_p", len, buffer); ecparam_print_var(out, ec_a, "ec_a", len, buffer); ecparam_print_var(out, ec_b, "ec_b", len, buffer); ecparam_print_var(out, ec_gen, "ec_gen", len, buffer); ecparam_print_var(out, ec_order, "ec_order", len, buffer); ecparam_print_var(out, ec_cofactor, "ec_cofactor", len, buffer); BIO_printf(out, "\n\n"); BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n\t{\n", len); BIO_printf(out, "\tint ok=0;\n"); BIO_printf(out, "\tEC_GROUP *group = NULL;\n"); BIO_printf(out, "\tEC_POINT *point = NULL;\n"); BIO_printf(out, "\tBIGNUM *tmp_1 = NULL, *tmp_2 = NULL, " "*tmp_3 = NULL;\n\n"); BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_p_%d, " "sizeof(ec_p_%d), NULL)) == NULL)\n\t\t" "goto err;\n", len, len); BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_a_%d, " "sizeof(ec_a_%d), NULL)) == NULL)\n\t\t" "goto err;\n", len, len); BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_b_%d, " "sizeof(ec_b_%d), NULL)) == NULL)\n\t\t" "goto err;\n", len, len); if (is_prime) { BIO_printf(out, "\tif ((group = EC_GROUP_new_curve_" "GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)" "\n\t\tgoto err;\n\n"); } else { /* TODO */ goto end; } BIO_printf(out, "\t/* build generator */\n"); BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_gen_%d, " "sizeof(ec_gen_%d), tmp_1)) == NULL)" "\n\t\tgoto err;\n", len, len); BIO_printf(out, "\tpoint = EC_POINT_bn2point(group, tmp_1, " "NULL, NULL);\n"); BIO_printf(out, "\tif (point == NULL)\n\t\tgoto err;\n"); BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_order_%d, " "sizeof(ec_order_%d), tmp_2)) == NULL)" "\n\t\tgoto err;\n", len, len); BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_cofactor_%d, " "sizeof(ec_cofactor_%d), tmp_3)) == NULL)" "\n\t\tgoto err;\n", len, len); BIO_printf(out, "\tif (!EC_GROUP_set_generator(group, point," " tmp_2, tmp_3))\n\t\tgoto err;\n"); BIO_printf(out, "\n\tok=1;\n"); BIO_printf(out, "err:\n"); BIO_printf(out, "\tif (tmp_1)\n\t\tBN_free(tmp_1);\n"); BIO_printf(out, "\tif (tmp_2)\n\t\tBN_free(tmp_2);\n"); BIO_printf(out, "\tif (tmp_3)\n\t\tBN_free(tmp_3);\n"); BIO_printf(out, "\tif (point)\n\t\tEC_POINT_free(point);\n"); BIO_printf(out, "\tif (!ok)\n"); BIO_printf(out, "\t\t{\n"); BIO_printf(out, "\t\tEC_GROUP_free(group);\n"); BIO_printf(out, "\t\tgroup = NULL;\n"); BIO_printf(out, "\t\t}\n"); BIO_printf(out, "\treturn(group);\n\t}\n"); } if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_ECPKParameters_bio(out, group); else if (outformat == FORMAT_PEM) i = PEM_write_bio_ECPKParameters(out, group); else { BIO_printf(bio_err, "bad output format specified for" " outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write elliptic " "curve parameters\n"); ERR_print_errors(bio_err); goto end; } } if (genkey) { EC_KEY *eckey = EC_KEY_new(); if (eckey == NULL) goto end; if (EC_KEY_set_group(eckey, group) == 0) goto end; if (!EC_KEY_generate_key(eckey)) { EC_KEY_free(eckey); goto end; } if (outformat == FORMAT_ASN1) i = i2d_ECPrivateKey_bio(out, eckey); else if (outformat == FORMAT_PEM) i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL); else { BIO_printf(bio_err, "bad output format specified " "for outfile\n"); EC_KEY_free(eckey); goto end; } EC_KEY_free(eckey); } ret = 0; end: if (ec_p) BN_free(ec_p); if (ec_a) BN_free(ec_a); if (ec_b) BN_free(ec_b); if (ec_gen) BN_free(ec_gen); if (ec_order) BN_free(ec_order); if (ec_cofactor) BN_free(ec_cofactor); if (buffer) free(buffer); if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (group != NULL) EC_GROUP_free(group); return (ret); }
int test_builtin(BIO *out) { size_t 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; const unsigned char *sig_ptr; unsigned char *sig_ptr2; 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 (!RAND_pseudo_bytes(digest, 20) || !RAND_pseudo_bytes(wrong_digest, 20)) { BIO_printf(out, "ERROR: unable to get random data\n"); goto builtin_err; } /* create and verify a ecdsa signature with every availble curve * (with ) */ BIO_printf(out, "\ntesting ECDSA_sign() and ECDSA_verify() " "with some internal curves:\n"); static const int kCurveNIDs[] = {NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_undef}; /* now create and verify a signature for every curve */ for (n = 0; kCurveNIDs[n] != NID_undef; n++) { unsigned char dirt, offset; nid = kCurveNIDs[n]; /* create new ecdsa key (== EC_KEY) */ eckey = EC_KEY_new(); if (eckey == NULL) { goto builtin_err; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { goto builtin_err; } if (!EC_KEY_set_group(eckey, group)) { goto builtin_err; } EC_GROUP_free(group); degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); if (degree < 160) { /* Too small to test. */ EC_KEY_free(eckey); eckey = NULL; continue; } BIO_printf(out, "%s: ", OBJ_nid2sn(nid)); /* create key */ if (!EC_KEY_generate_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } /* create second key */ wrong_eckey = EC_KEY_new(); if (wrong_eckey == NULL) { goto builtin_err; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { goto builtin_err; } if (EC_KEY_set_group(wrong_eckey, group) == 0) { goto builtin_err; } EC_GROUP_free(group); if (!EC_KEY_generate_key(wrong_eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* check key */ if (!EC_KEY_check_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* create signature */ sig_len = ECDSA_size(eckey); signature = OPENSSL_malloc(sig_len); if (signature == NULL) { goto builtin_err; } if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature */ 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); /* verify signature with the wrong key */ if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong digest */ if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* 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; ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len); if (ecdsa_sig == 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; raw_buf = OPENSSL_malloc(buf_len); if (raw_buf == 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_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); 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_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); 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; builtin_err: if (eckey) 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); return ret; }