/* Padding is ignored. We use OAEP by default. Parameter is to support more paddings in the future */ soter_status_t soter_asym_cipher_init(soter_asym_cipher_t* asym_cipher, const void* key, const size_t key_length, soter_asym_cipher_padding_t pad) { EVP_PKEY *pkey; if ((!asym_cipher) || (SOTER_ASYM_CIPHER_OAEP != pad)) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_new(); if (!pkey) { return SOTER_NO_MEMORY; } /* Only RSA supports asymmetric encryption */ if (!EVP_PKEY_set_type(pkey, EVP_PKEY_RSA)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } asym_cipher->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!(asym_cipher->pkey_ctx)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } SOTER_IF_FAIL(soter_asym_cipher_import_key(asym_cipher, key, key_length)==SOTER_SUCCESS, (EVP_PKEY_free(pkey), EVP_PKEY_CTX_free(asym_cipher->pkey_ctx))); return SOTER_SUCCESS; }
/* * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting * NID and parameters */ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) { ASN1_OBJECT *palg_obj = NULL; int ptype = V_ASN1_UNDEF; int pkey_nid = NID_undef, param_nid = NID_undef; ASN1_STRING *pval = NULL; const unsigned char *p; GOST_KEY_PARAMS *gkp = NULL; if (!pkey || !palg) return 0; X509_ALGOR_get0(&palg_obj, &ptype, (void **)&pval, palg); if (ptype != V_ASN1_SEQUENCE) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOST_R_BAD_KEY_PARAMETERS_FORMAT); return 0; } p = pval->data; pkey_nid = OBJ_obj2nid(palg_obj); gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length); if (!gkp) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOST_R_BAD_PKEY_PARAMETERS_FORMAT); return 0; } param_nid = OBJ_obj2nid(gkp->key_params); GOST_KEY_PARAMS_free(gkp); if (!EVP_PKEY_set_type(pkey, pkey_nid)) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR); return 0; } return gost_decode_nid_params(pkey, pkey_nid, param_nid); }
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { if (!EVP_PKEY_set_type(pkey, type)) return 0; pkey->pkey.ptr=(char*)key; return (key != NULL); }
EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp, long length) { EVP_PKEY *ret = NULL; const unsigned char *p = *pp; if ((a == NULL) || (*a == NULL)) { if ((ret = EVP_PKEY_new()) == NULL) return NULL; } else ret = *a; if (type != EVP_PKEY_id(ret) && !EVP_PKEY_set_type(ret, type)) goto err; if (ret->ameth == NULL || ret->ameth->param_decode == NULL) { ASN1err(ASN1_F_D2I_KEYPARAMS, ASN1_R_UNSUPPORTED_TYPE); goto err; } if (!ret->ameth->param_decode(ret, &p, length)) goto err; if (a != NULL) (*a) = ret; return ret; err: if (a == NULL || *a != ret) EVP_PKEY_free(ret); return NULL; }
/* * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting * NID and parameters */ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) { ASN1_OBJECT *palg_obj = NULL; int ptype = V_ASN1_UNDEF; int pkey_nid = NID_undef, param_nid = NID_undef; void *_pval; ASN1_STRING *pval = NULL; const unsigned char *p; GOST_KEY_PARAMS *gkp = NULL; X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg); pval = _pval; if (ptype != V_ASN1_SEQUENCE) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOST_R_BAD_KEY_PARAMETERS_FORMAT); return 0; } p = pval->data; pkey_nid = OBJ_obj2nid(palg_obj); gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length); if (!gkp) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOST_R_BAD_PKEY_PARAMETERS_FORMAT); return 0; } param_nid = OBJ_obj2nid(gkp->key_params); GOST_KEY_PARAMS_free(gkp); if(!EVP_PKEY_set_type(pkey, pkey_nid)) { GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR); return 0; } switch (pkey_nid) { case NID_id_GostR3410_94: { DSA *dsa = EVP_PKEY_get0(pkey); if (!dsa) { dsa = DSA_new(); if (!EVP_PKEY_assign(pkey, pkey_nid, dsa)) return 0; } if (!fill_GOST94_params(dsa, param_nid)) return 0; break; } case NID_id_GostR3410_2001: { EC_KEY *ec = EVP_PKEY_get0(pkey); if (!ec) { ec = EC_KEY_new(); if (!EVP_PKEY_assign(pkey, pkey_nid, ec)) return 0; } if (!fill_GOST2001_params(ec, param_nid)) return 0; } } return 1; }
static int set_pkey_type_from_str(EVP_PKEY *pkey, const char *name, size_t len) { int nid = public_key_type_from_str(name, len); if (nid == NID_undef) { return 0; } return EVP_PKEY_set_type(pkey, nid); }
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; if (key == NULL) goto error; if (key->pkey != NULL) { return EVP_PKEY_dup(key->pkey); } if (key->public_key == NULL) goto error; if ((ret = EVP_PKEY_new()) == NULL) { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, ERR_R_MALLOC_FAILURE); goto error; } if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_UNSUPPORTED_ALGORITHM); goto error; } if (ret->ameth->pub_decode) { if (!ret->ameth->pub_decode(ret, key)) { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_PUBLIC_KEY_DECODE_ERROR); goto error; } } else { OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_METHOD_NOT_SUPPORTED); goto error; } /* Check to see if another thread set key->pkey first */ CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); if (key->pkey) { CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); EVP_PKEY_free(ret); ret = key->pkey; } else { key->pkey = ret; CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); } return EVP_PKEY_dup(ret); error: if (ret != NULL) EVP_PKEY_free(ret); return(NULL); }
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { if (!EVP_PKEY_set_type(pkey, type)) { return 0; } pkey->pkey.ptr = key; return key != NULL; }
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { if (to->type == EVP_PKEY_NONE) { if (EVP_PKEY_set_type(to, from->type) == 0) return 0; } else if (to->type != from->type) { EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES); goto err; } if (EVP_PKEY_missing_parameters(from)) { EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS); goto err; } if (!EVP_PKEY_missing_parameters(to)) { if (EVP_PKEY_cmp_parameters(to, from) == 1) return 1; EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS); return 0; } if (from->ameth && from->ameth->param_copy) return from->ameth->param_copy(to, from); err: return 0; }
EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) { EVP_PKEY *ret; if ((a == NULL) || (*a == NULL)) { if ((ret = EVP_PKEY_new()) == NULL) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); return (NULL); } } else ret = *a; if (!EVP_PKEY_set_type(ret, type)) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); goto err; } switch (EVP_PKEY_id(ret)) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); goto err; } break; #endif #ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: /* TMP UGLY CAST */ if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); goto err; } break; #endif #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) { ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); goto err; } break; #endif default: ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; /* break; */ } if (a != NULL) (*a) = ret; return (ret); err: if (a == NULL || *a != ret) EVP_PKEY_free(ret); return (NULL); }
soter_status_t soter_verify_init_rsa_pss_pkcs8(soter_sign_ctx_t* ctx, const void* private_key, const size_t private_key_length, const void* public_key, const size_t public_key_length) { /* pkey_ctx init */ EVP_PKEY* pkey; pkey = EVP_PKEY_new(); if (!pkey) { return SOTER_NO_MEMORY; } if (!EVP_PKEY_set_type(pkey, EVP_PKEY_RSA)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!(ctx->pkey_ctx)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } if (private_key && private_key_length != 0) { if (soter_rsa_import_key(pkey, private_key, private_key_length) != SOTER_SUCCESS) { soter_verify_cleanup_rsa_pss_pkcs8(ctx); return SOTER_FAIL; } } if (public_key && public_key_length != 0) { if (soter_rsa_import_key(pkey, public_key, public_key_length) != SOTER_SUCCESS) { soter_verify_cleanup_rsa_pss_pkcs8(ctx); return SOTER_FAIL; } } /*md_ctx init*/ ctx->md_ctx = EVP_MD_CTX_create(); if (!(ctx->md_ctx)) { soter_verify_cleanup_rsa_pss_pkcs8(ctx); return SOTER_NO_MEMORY; } EVP_PKEY_CTX* md_pkey_ctx = NULL; if (!EVP_DigestVerifyInit(ctx->md_ctx, &md_pkey_ctx, EVP_sha256(), NULL, pkey)) { soter_verify_cleanup_rsa_pss_pkcs8(ctx); return SOTER_FAIL; } if (!EVP_PKEY_CTX_set_rsa_padding(md_pkey_ctx, RSA_PKCS1_PSS_PADDING)) { soter_verify_cleanup_rsa_pss_pkcs8(ctx); return SOTER_FAIL; } if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(md_pkey_ctx, -2)) { soter_verify_cleanup_rsa_pss_pkcs8(ctx); return SOTER_FAIL; } return SOTER_SUCCESS; }
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp, long len) { EVP_PKEY *ret; if (out == NULL || *out == NULL) { ret = EVP_PKEY_new(); if (ret == NULL) { OPENSSL_PUT_ERROR(EVP, ERR_R_EVP_LIB); return NULL; } } else { ret = *out; } if (!EVP_PKEY_set_type(ret, type)) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; } const uint8_t *in = *inp; if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &in, len)) { if (ret->ameth->priv_decode) { /* Reset |in| in case |old_priv_decode| advanced it on error. */ in = *inp; PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &in, len); if (!p8) { goto err; } EVP_PKEY_free(ret); ret = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (ret == NULL) { goto err; } } else { OPENSSL_PUT_ERROR(EVP, ERR_R_ASN1_LIB); goto err; } } if (out != NULL) { *out = ret; } *inp = in; return ret; err: if (out == NULL || *out != ret) { EVP_PKEY_free(ret); } return NULL; }
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret = NULL; if (key == NULL) goto error; if (key->pkey != NULL) { CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); return key->pkey; } if (key->public_key == NULL) goto error; if ((ret = EVP_PKEY_new()) == NULL) { X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); goto error; } if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) { X509err(X509_F_X509_PUBKEY_GET, X509_R_UNSUPPORTED_ALGORITHM); goto error; } if (ret->ameth->pub_decode) { if (!ret->ameth->pub_decode(ret, key)) { X509err(X509_F_X509_PUBKEY_GET, X509_R_PUBLIC_KEY_DECODE_ERROR); goto error; } } else { X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED); goto error; } /* Check to see if another thread set key->pkey first */ CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); if (key->pkey) { CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); EVP_PKEY_free(ret); ret = key->pkey; } else { key->pkey = ret; CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); } CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return ret; error: EVP_PKEY_free(ret); return (NULL); }
soter_status_t soter_verify_init_ecdsa_none_pkcs8(soter_sign_ctx_t* ctx, const void* private_key, const size_t private_key_length, const void* public_key, const size_t public_key_length) { /* pkey_ctx init */ EVP_PKEY* pkey; pkey = EVP_PKEY_new(); if (!pkey) { return SOTER_NO_MEMORY; } if (!EVP_PKEY_set_type(pkey, EVP_PKEY_EC)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!(ctx->pkey_ctx)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } /* TODO: Review needed */ if ((private_key) && (private_key_length)) { if (soter_ec_import_key(pkey, private_key, private_key_length) != SOTER_SUCCESS) { soter_verify_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } } if ((public_key) && (public_key_length)) { if (soter_ec_import_key(pkey, public_key, public_key_length) != SOTER_SUCCESS) { soter_verify_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } } /*md_ctx init*/ ctx->md_ctx = EVP_MD_CTX_create(); if (!(ctx->md_ctx)) { soter_verify_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_NO_MEMORY; } if (!EVP_DigestVerifyInit(ctx->md_ctx, NULL, EVP_sha256(), NULL, pkey)) { soter_verify_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } return SOTER_SUCCESS; }
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { EVP_PKEY *pkey = NULL; ASN1_OBJECT *algoid; char obj_tmp[80]; if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) return NULL; if (!(pkey = EVP_PKEY_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); return NULL; } if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); i2t_ASN1_OBJECT(obj_tmp, 80, algoid); ERR_add_error_data(2, "TYPE=", obj_tmp); goto error; } if (pkey->ameth->priv_decode) { if (!pkey->ameth->priv_decode(pkey, p8)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_PRIVATE_KEY_DECODE_ERROR); goto error; } } else { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED); goto error; } return pkey; error: EVP_PKEY_free (pkey); return NULL; }
soter_status_t soter_asym_ka_init(soter_asym_ka_t* asym_ka_ctx, soter_asym_ka_alg_t alg) { EVP_PKEY *pkey; int nid = soter_alg_to_curve_nid(alg); if ((!asym_ka_ctx) || (0 == nid)) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_new(); if (!pkey) { return SOTER_NO_MEMORY; } if (!EVP_PKEY_set_type(pkey, EVP_PKEY_EC)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } asym_ka_ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!(asym_ka_ctx->pkey_ctx)) { EVP_PKEY_free(pkey); return SOTER_FAIL; } EC_KEY* ec = EC_KEY_new_by_curve_name(nid); if( !ec ){ EVP_PKEY_CTX_free(asym_ka_ctx->pkey_ctx); return SOTER_FAIL; } if(1!=EVP_PKEY_set1_EC_KEY(pkey, ec)){ EVP_PKEY_CTX_free(asym_ka_ctx->pkey_ctx); EC_KEY_free(ec); return SOTER_FAIL; } EC_KEY_free(ec); return SOTER_SUCCESS; }
EVP_PKEY *EVP_parse_public_key(CBS *cbs) { // Parse the SubjectPublicKeyInfo. CBS spki, algorithm, key; int type; uint8_t padding; if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || !parse_key_type(&algorithm, &type) || !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) || CBS_len(&spki) != 0 || // Every key type defined encodes the key as a byte string with the same // conversion to BIT STRING. !CBS_get_u8(&key, &padding) || padding != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return NULL; } // Set up an |EVP_PKEY| of the appropriate type. EVP_PKEY *ret = EVP_PKEY_new(); if (ret == NULL || !EVP_PKEY_set_type(ret, type)) { goto err; } // Call into the type-specific SPKI decoding function. if (ret->ameth->pub_decode == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); goto err; } if (!ret->ameth->pub_decode(ret, &algorithm, &key)) { goto err; } return ret; err: EVP_PKEY_free(ret); return NULL; }
soter_status_t soter_rsa_key_pair_gen_init(soter_rsa_key_pair_gen_t* ctx, const unsigned key_length){ EVP_PKEY *pkey; pkey = EVP_PKEY_new(); SOTER_CHECK(pkey); /* Only RSA supports asymmetric encryption */ SOTER_IF_FAIL(EVP_PKEY_set_type(pkey, EVP_PKEY_RSA), EVP_PKEY_free(pkey)); ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); SOTER_IF_FAIL(ctx->pkey_ctx,EVP_PKEY_free(pkey)); BIGNUM *pub_exp; SOTER_IF_FAIL(EVP_PKEY_keygen_init(ctx->pkey_ctx), EVP_PKEY_CTX_free(ctx->pkey_ctx)); /* Although it seems that OpenSSL/LibreSSL use 0x10001 as default public exponent, we will set it explicitly just in case */ pub_exp = BN_new(); SOTER_CHECK(pub_exp); SOTER_IF_FAIL(BN_set_word(pub_exp, RSA_F4), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); SOTER_IF_FAIL(1 <= EVP_PKEY_CTX_ctrl(ctx->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pub_exp), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); /* Override default key size for RSA key. Currently OpenSSL has default key size of 1024. LibreSSL has 2048. We will put 2048 explicitly */ SOTER_IF_FAIL((1 <= EVP_PKEY_CTX_ctrl(ctx->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_KEYGEN_BITS, rsa_key_length(key_length), NULL)), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); SOTER_IF_FAIL(EVP_PKEY_keygen(ctx->pkey_ctx, &pkey), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); return SOTER_SUCCESS; }
EVP_PKEY *EVP_parse_private_key(CBS *cbs) { // Parse the PrivateKeyInfo. CBS pkcs8, algorithm, key; uint64_t version; int type; if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&pkcs8, &version) || version != 0 || !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || !parse_key_type(&algorithm, &type) || !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return NULL; } // A PrivateKeyInfo ends with a SET of Attributes which we ignore. // Set up an |EVP_PKEY| of the appropriate type. EVP_PKEY *ret = EVP_PKEY_new(); if (ret == NULL || !EVP_PKEY_set_type(ret, type)) { goto err; } // Call into the type-specific PrivateKeyInfo decoding function. if (ret->ameth->priv_decode == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); goto err; } if (!ret->ameth->priv_decode(ret, &algorithm, &key)) { goto err; } return ret; err: EVP_PKEY_free(ret); return NULL; }
static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key) { EVP_PKEY *pkey = EVP_PKEY_new(); if (pkey == NULL) { X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE); return -1; } if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) { X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM); goto error; } if (pkey->ameth->pub_decode) { /* * Treat any failure of pub_decode as a decode error. In * future we could have different return codes for decode * errors and fatal errors such as malloc failure. */ if (!pkey->ameth->pub_decode(pkey, key)) { X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR); goto error; } } else { X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED); goto error; } *ppkey = pkey; return 1; error: EVP_PKEY_free(pkey); return 0; }
/* * Process a key_share extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. * If a failure occurs then |*al| is set to an appropriate alert value. */ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, int *al) { unsigned int group_id; PACKET key_share_list, encoded_pt; const unsigned char *clntcurves, *srvrcurves; size_t clnt_num_curves, srvr_num_curves; int group_nid, found = 0; unsigned int curve_flags; if (s->hit) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* Get our list of supported curves */ if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* * Get the clients list of supported curves. * TODO(TLS1.3): We should validate that we actually received * supported_groups! */ if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } while (PACKET_remaining(&key_share_list) > 0) { if (!PACKET_get_net_2(&key_share_list, &group_id) || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* * If we already found a suitable key_share we loop through the * rest to verify the structure, but don't process them. */ if (found) continue; /* Check if this share is in supported_groups sent from client */ if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } /* Check if this share is for a group we can use */ if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) { /* Share not suitable */ continue; } group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags); if (group_nid == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); return 0; } if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { /* Can happen for some curves, e.g. X25519 */ EVP_PKEY *key = EVP_PKEY_new(); if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_free(key); return 0; } s->s3->peer_tmp = key; } else { /* Set up EVP_PKEY with named curve as parameters */ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, group_nid) <= 0 || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_CTX_free(pctx); return 0; } EVP_PKEY_CTX_free(pctx); pctx = NULL; } s->s3->group_id = group_id; if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } return 1; }
static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len, const unsigned char *params, int params_len, unsigned char *data, int data_len, unsigned char *signat, int signat_len) { EVP_PKEY *pkey; EVP_PKEY_CTX *pkey_ctx; EC_POINT *P; BIGNUM *X, *Y; ASN1_OCTET_STRING *octet; const EC_GROUP *group = NULL; char paramset[2] = "A"; int r = -1, ret_vrf = 0; pkey = EVP_PKEY_new(); if (!pkey) return CKR_HOST_MEMORY; r = EVP_PKEY_set_type(pkey, NID_id_GostR3410_2001); if (r == 1) { pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pkey_ctx) { EVP_PKEY_free(pkey); return CKR_HOST_MEMORY; } /* FIXME: fully check params[] */ if (params_len > 0 && params[params_len - 1] >= 1 && params[params_len - 1] <= 3) { paramset[0] += params[params_len - 1] - 1; r = EVP_PKEY_CTX_ctrl_str(pkey_ctx, "paramset", paramset); } else r = -1; if (r == 1) r = EVP_PKEY_paramgen_init(pkey_ctx); if (r == 1) r = EVP_PKEY_paramgen(pkey_ctx, &pkey); if (r == 1 && EVP_PKEY_get0(pkey) != NULL) group = EC_KEY_get0_group(EVP_PKEY_get0(pkey)); r = -1; if (group) octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey, (long)pubkey_len); if (group && octet) { reverse(octet->data, octet->length); Y = BN_bin2bn(octet->data, octet->length / 2, NULL); X = BN_bin2bn((const unsigned char*)octet->data + octet->length / 2, octet->length / 2, NULL); ASN1_OCTET_STRING_free(octet); P = EC_POINT_new(group); if (P && X && Y) r = EC_POINT_set_affine_coordinates_GFp(group, P, X, Y, NULL); BN_free(X); BN_free(Y); if (r == 1 && EVP_PKEY_get0(pkey) && P) r = EC_KEY_set_public_key(EVP_PKEY_get0(pkey), P); EC_POINT_free(P); } if (r == 1) { r = EVP_PKEY_verify_init(pkey_ctx); reverse(data, data_len); if (r == 1) ret_vrf = EVP_PKEY_verify(pkey_ctx, signat, signat_len, data, data_len); } } EVP_PKEY_CTX_free(pkey_ctx); EVP_PKEY_free(pkey); if (r != 1) return CKR_GENERAL_ERROR; return ret_vrf == 1 ? CKR_OK : CKR_SIGNATURE_INVALID; }
/* * Process a key_share extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. * If a failure occurs then |*al| is set to an appropriate alert value. */ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 unsigned int group_id; PACKET key_share_list, encoded_pt; const unsigned char *clntcurves, *srvrcurves; size_t clnt_num_curves, srvr_num_curves; int group_nid, found = 0; unsigned int curve_flags; if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* Get our list of supported curves */ if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* Get the clients list of supported curves. */ if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (clnt_num_curves == 0) { /* * This can only happen if the supported_groups extension was not sent, * because we verify that the length is non-zero when we process that * extension. */ *al = SSL_AD_MISSING_EXTENSION; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); return 0; } while (PACKET_remaining(&key_share_list) > 0) { if (!PACKET_get_net_2(&key_share_list, &group_id) || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* * If we already found a suitable key_share we loop through the * rest to verify the structure, but don't process them. */ if (found) continue; /* Check if this share is in supported_groups sent from client */ if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } /* Check if this share is for a group we can use */ if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) { /* Share not suitable */ continue; } group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags); if (group_nid == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); return 0; } if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { /* Can happen for some curves, e.g. X25519 */ EVP_PKEY *key = EVP_PKEY_new(); if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_free(key); return 0; } s->s3->peer_tmp = key; } else { /* Set up EVP_PKEY with named curve as parameters */ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, group_nid) <= 0 || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_CTX_free(pctx); return 0; } EVP_PKEY_CTX_free(pctx); pctx = NULL; } s->s3->group_id = group_id; if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } #endif return 1; }
/* * Key parameter decoder. */ static OSSL_STORE_INFO *try_decode_params(const char *pem_name, const char *pem_header, const unsigned char *blob, size_t len, void **pctx, int *matchcount, const UI_METHOD *ui_method, void *ui_data) { OSSL_STORE_INFO *store_info = NULL; int slen = 0; EVP_PKEY *pkey = NULL; const EVP_PKEY_ASN1_METHOD *ameth = NULL; int ok = 0; if (pem_name != NULL) { if ((slen = pem_check_suffix(pem_name, "PARAMETERS")) == 0) return NULL; *matchcount = 1; } if (slen > 0) { if ((pkey = EVP_PKEY_new()) == NULL) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB); return NULL; } if (EVP_PKEY_set_type_str(pkey, pem_name, slen) && (ameth = EVP_PKEY_get0_asn1(pkey)) != NULL && ameth->param_decode != NULL && ameth->param_decode(pkey, &blob, len)) ok = 1; } else { int i; EVP_PKEY *tmp_pkey = NULL; for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { const unsigned char *tmp_blob = blob; if (tmp_pkey == NULL && (tmp_pkey = EVP_PKEY_new()) == NULL) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB); break; } ameth = EVP_PKEY_asn1_get0(i); if (ameth->pkey_flags & ASN1_PKEY_ALIAS) continue; if (EVP_PKEY_set_type(tmp_pkey, ameth->pkey_id) && (ameth = EVP_PKEY_get0_asn1(tmp_pkey)) != NULL && ameth->param_decode != NULL && ameth->param_decode(tmp_pkey, &tmp_blob, len)) { if (pkey != NULL) EVP_PKEY_free(tmp_pkey); else pkey = tmp_pkey; tmp_pkey = NULL; (*matchcount)++; } } EVP_PKEY_free(tmp_pkey); if (*matchcount == 1) { ok = 1; } } if (ok) store_info = OSSL_STORE_INFO_new_PARAMS(pkey); if (store_info == NULL) EVP_PKEY_free(pkey); return store_info; }
soter_status_t soter_sign_init_ecdsa_none_pkcs8(soter_sign_ctx_t* ctx, const void* private_key, const size_t private_key_length, const void* public_key, const size_t public_key_length) { /* pkey_ctx init */ EVP_PKEY *pkey; pkey = EVP_PKEY_new(); if (!pkey){ return SOTER_NO_MEMORY; } if (!EVP_PKEY_set_type(pkey, EVP_PKEY_EC)){ EVP_PKEY_free(pkey); return SOTER_FAIL; } ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!(ctx->pkey_ctx)){ EVP_PKEY_free(pkey); return SOTER_FAIL; } if (!EVP_PKEY_paramgen_init(ctx->pkey_ctx)){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } if (!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx->pkey_ctx, NID_X9_62_prime256v1)){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } if (!EVP_PKEY_paramgen(ctx->pkey_ctx, &pkey)){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } if((!private_key)&&(!public_key)){ if(soter_ec_gen_key(ctx->pkey_ctx)!=SOTER_SUCCESS){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } }else{ if(private_key!=NULL){ if(soter_ec_import_key(pkey, private_key, private_key_length)!=SOTER_SUCCESS){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } } if(public_key!=NULL){ if(soter_ec_import_key(pkey, public_key, public_key_length)!=SOTER_SUCCESS){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } } } /*md_ctx init*/ ctx->md_ctx = EVP_MD_CTX_create(); if(!(ctx->md_ctx)){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_NO_MEMORY; } if(EVP_DigestSignInit(ctx->md_ctx, NULL, EVP_sha256(), NULL, pkey)!=1){ soter_sign_cleanup_ecdsa_none_pkcs8(ctx); return SOTER_FAIL; } return SOTER_SUCCESS; }
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) { EVP_PKEY *ret; const unsigned char *p = *pp; if ((a == NULL) || (*a == NULL)) { if ((ret = EVP_PKEY_new()) == NULL) { ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB); return (NULL); } } else { ret = *a; #ifndef OPENSSL_NO_ENGINE if (ret->engine) { ENGINE_finish(ret->engine); ret->engine = NULL; } #endif } if (!EVP_PKEY_set_type(ret, type)) { ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; } if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &p, length)) { if (ret->ameth->priv_decode) { EVP_PKEY *tmp; PKCS8_PRIV_KEY_INFO *p8 = NULL; p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); if (!p8) goto err; tmp = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (tmp == NULL) goto err; EVP_PKEY_free(ret); ret = tmp; } else { ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB); goto err; } } *pp = p; if (a != NULL) (*a) = ret; return (ret); err: if ((ret != NULL) && ((a == NULL) || (*a != ret))) EVP_PKEY_free(ret); return (NULL); }