static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) { const EC_KEY *ec_key = key->pkey.ec; // Omit the redundant copy of the curve name. This contradicts RFC 5915 but // aligns with PKCS #11. SEC 1 only says they may be omitted if known by other // means. Both OpenSSL and NSS omit the redundant parameters, so we omit them // as well. unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS; // See RFC 5915. CBB pkcs8, algorithm, oid, private_key; if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) || !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) || !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) || !CBB_flush(out)) { OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); return 0; } return 1; }
static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) { EC_KEY *ec_key; unsigned char *ep, *p; int eplen, ptype; void *pval; unsigned int tmp_flags, old_flags; ec_key = pkey->pkey.ec; if (!eckey_param2type(&ptype, &pval, ec_key)) { ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); return 0; } /* set the private key */ /* do not include the parameters in the SEC1 private key * see PKCS#11 12.11 */ old_flags = EC_KEY_get_enc_flags(ec_key); tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; EC_KEY_set_enc_flags(ec_key, tmp_flags); eplen = i2d_ECPrivateKey(ec_key, NULL); if (!eplen) { EC_KEY_set_enc_flags(ec_key, old_flags); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); return 0; } ep = (unsigned char *) OPENSSL_malloc(eplen); if (!ep) { EC_KEY_set_enc_flags(ec_key, old_flags); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); return 0; } p = ep; if (!i2d_ECPrivateKey(ec_key, &p)) { EC_KEY_set_enc_flags(ec_key, old_flags); OPENSSL_free(ep); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); return 0; } /* restore old encoding flags */ EC_KEY_set_enc_flags(ec_key, old_flags); if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, ptype, pval, ep, eplen)) return 0; return 1; }
static int openssl_ec_key_parse(lua_State*L) { EC_KEY* ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key"); int basic = luaL_opt(L,lua_toboolean, 2, 0); const EC_POINT* point = EC_KEY_get0_public_key(ec); const EC_GROUP* group = EC_KEY_get0_group(ec); const BIGNUM *priv = EC_KEY_get0_private_key(ec); lua_newtable(L); if (basic) { BIGNUM* x = BN_new(); BIGNUM* y = BN_new(); AUXILIAR_SET(L, -1, "enc_flag", EC_KEY_get_enc_flags(ec), integer); AUXILIAR_SET(L, -1, "conv_form", EC_KEY_get_conv_form(ec), integer); AUXILIAR_SET(L, -1, "curve_name", EC_GROUP_get_curve_name(group), integer); AUXILIAR_SETOBJECT(L, BN_dup(priv), "openssl.bn", -1, "d"); if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, NULL) == 1) { AUXILIAR_SETOBJECT(L, x, "openssl.bn", -1, "x"); AUXILIAR_SETOBJECT(L, y, "openssl.bn", -1, "y"); }; } else { AUXILIAR_SET(L, -1, "enc_flag", EC_KEY_get_enc_flags(ec), integer); AUXILIAR_SET(L, -1, "conv_form", EC_KEY_get_conv_form(ec), integer); point = EC_POINT_dup(point, group); AUXILIAR_SETOBJECT(L, point, "openssl.ec_point", -1, "pub_key"); group = EC_GROUP_dup(group); AUXILIAR_SETOBJECT(L, group, "openssl.ec_group", -1, "group"); OPENSSL_PKEY_GET_BN(priv, priv_key); } return 1; };
static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) { EC_KEY ec_key = *(pkey->pkey.ec); uint8_t *ep, *p; int eplen, ptype; void *pval; unsigned int old_flags; if (!eckey_param2type(&ptype, &pval, &ec_key)) { ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); return 0; } /* set the private key */ /* do not include the parameters in the SEC1 private key * see PKCS#11 12.11 */ old_flags = EC_KEY_get_enc_flags(&ec_key); EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); eplen = i2d_ECPrivateKey(&ec_key, NULL); if (!eplen) { ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); return 0; } ep = malloc(eplen); if (ep == NULL) { ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); return 0; } p = ep; if (!i2d_ECPrivateKey(&ec_key, &p)) { free(ep); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); return 0; } if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, ptype, pval, ep, eplen)) return 0; return 1; }
static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey) { EC_KEY *ec_key; const EC_GROUP *group; unsigned char *p, *pp; int nid, i, ret = 0; unsigned int tmp_flags, old_flags; ec_key = pkey->pkey.ec; if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, EVP_R_MISSING_PARAMETERS); return 0; } /* set the ec parameters OID */ if (p8->pkeyalg->algorithm) ASN1_OBJECT_free(p8->pkeyalg->algorithm); p8->pkeyalg->algorithm = OBJ_nid2obj(NID_X9_62_id_ecPublicKey); /* set the ec parameters */ if (p8->pkeyalg->parameter) { ASN1_TYPE_free(p8->pkeyalg->parameter); p8->pkeyalg->parameter = NULL; } if ((p8->pkeyalg->parameter = ASN1_TYPE_new()) == NULL) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); return 0; } if (EC_GROUP_get_asn1_flag(group) && (nid = EC_GROUP_get_curve_name(group))) { /* we have a 'named curve' => just set the OID */ p8->pkeyalg->parameter->type = V_ASN1_OBJECT; p8->pkeyalg->parameter->value.object = OBJ_nid2obj(nid); } else /* explicit parameters */ { if ((i = i2d_ECParameters(ec_key, NULL)) == 0) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); return 0; } if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); return 0; } pp = p; if (!i2d_ECParameters(ec_key, &pp)) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); OPENSSL_free(p); return 0; } p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; if ((p8->pkeyalg->parameter->value.sequence = ASN1_STRING_new()) == NULL) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_ASN1_LIB); OPENSSL_free(p); return 0; } ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, i); OPENSSL_free(p); } /* set the private key */ /* do not include the parameters in the SEC1 private key * see PKCS#11 12.11 */ old_flags = EC_KEY_get_enc_flags(pkey->pkey.ec); tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; EC_KEY_set_enc_flags(pkey->pkey.ec, tmp_flags); i = i2d_ECPrivateKey(pkey->pkey.ec, NULL); if (!i) { EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); return 0; } p = (unsigned char *) OPENSSL_malloc(i); if (!p) { EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); return 0; } pp = p; if (!i2d_ECPrivateKey(pkey->pkey.ec, &pp)) { EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); OPENSSL_free(p); return 0; } /* restore old encoding flags */ EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); switch(p8->broken) { case PKCS8_OK: p8->pkey->value.octet_string = ASN1_OCTET_STRING_new(); if (!p8->pkey->value.octet_string || !M_ASN1_OCTET_STRING_set(p8->pkey->value.octet_string, (const void *)p, i)) { EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); } else ret = 1; break; case PKCS8_NO_OCTET: /* RSA specific */ case PKCS8_NS_DB: /* DSA specific */ case PKCS8_EMBEDDED_PARAM: /* DSA specific */ default: EVPerr(EVP_F_ECKEY_PKEY2PKCS8,EVP_R_ENCODE_ERROR); } OPENSSL_cleanse(p, (size_t)i); OPENSSL_free(p); return ret; }