/* Allocates new gost_pmeth_data structure and assigns it as data */ static int pkey_gost_init(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); data = OPENSSL_malloc(sizeof(struct gost_pmeth_data)); if (!data) return 0; memset(data, 0, sizeof(struct gost_pmeth_data)); if (pkey && EVP_PKEY_get0(pkey)) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_94: data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey)); break; case NID_id_GostR3410_2001: data->sign_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group (EVP_PKEY_get0((EVP_PKEY *)pkey))); break; default: return 0; } } EVP_PKEY_CTX_set_data(ctx, data); return 1; }
/* * EVP_PKEY_METHOD callback derive. * Implements VKO R 34.10-2001/2012 algorithms */ int pkey_gost_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { /* * Public key of peer in the ctx field peerkey * Our private key in the ctx pkey * ukm is in the algorithm specific context data */ EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); int dgst_nid = NID_undef; if (!data || !data->shared_ukm) { GOSTerr(GOST_F_PKEY_GOST_EC_DERIVE, GOST_R_UKM_NOT_SET); return 0; } if (key == NULL) { *keylen = 32; return 32; } EVP_PKEY_get_default_digest_nid(my_key, &dgst_nid); *keylen = VKO_compute_key(key, 32, EC_KEY_get0_public_key(EVP_PKEY_get0(peer_key)), (EC_KEY *)EVP_PKEY_get0(my_key), data->shared_ukm, dgst_nid); return (*keylen) ? 1 : 0; }
int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd) { EVP_PKEY *pkey; int i; if (ri->type == CMS_RECIPINFO_TRANS) pkey = ri->d.ktri->pkey; else if (ri->type == CMS_RECIPINFO_AGREE) { EVP_PKEY_CTX *pctx = ri->d.kari->pctx; if (!pctx) return 0; pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (!pkey) return 0; } else return 0; if (!pkey->ameth || !pkey->ameth->pkey_ctrl) return 1; i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri); if (i == -2) { CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); return 0; } if (i <= 0) { CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE); return 0; } return 1; }
soter_status_t soter_asym_ka_export_key(soter_asym_ka_t* asym_ka_ctx, void* key, size_t* key_length, bool isprivate) { EVP_PKEY* pkey; if (!asym_ka_ctx) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_CTX_get0_pkey(asym_ka_ctx->pkey_ctx); if (!pkey) { return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_EC != EVP_PKEY_id(pkey)) { return SOTER_INVALID_PARAMETER; } if (isprivate) { return soter_engine_specific_to_ec_priv_key((const soter_engine_specific_ec_key_t*)pkey, (soter_container_hdr_t*)key, key_length); } return soter_engine_specific_to_ec_pub_key((const soter_engine_specific_ec_key_t*)pkey, (soter_container_hdr_t*)key, key_length); }
// Argh! This is one more of these OpenSSL-style schizophrenic APIs, where // depending on whether a parameter is NULL or not, different values are // expected... static int bcrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *outKey, size_t *outKeyLen) { *outKeyLen = X25519_KEYLEN; // First usage: a query for how many bytes the caller needs to allocate. if (outKey == NULL) return 1; // Second usage: writing into outkey the derived secret. // Note: this does NOT give you the actual bytes for the SECRET_HANDLE. (See // http://stackoverflow.com/questions/87694/im-using-wincrypt-for-diffie-hellman-can-i-export-the-shared-secret-in-plain // for something vaguely related). BCryptExportKey works for a KEY_HANDLE, not // a SECRET_HANDLE... and the type is defined as void* in the public Windows // 10 headers. bcrypt_x25519_key *pkey = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx)); bcrypt_x25519_key *peerkey = EVP_PKEY_get0(EVP_PKEY_CTX_get0_peerkey(ctx)); BCRYPT_SECRET_HANDLE hSecret = NULL; if (!NT_SUCCESS(BCryptSecretAgreement(pkey->pair, peerkey->pair, &hSecret, 0))) { fprintf(stderr, "Cannot compute agreement\n"); return 0; } // Writing out a dummy value in the meanwhile... memset(outKey, 0, X25519_KEYLEN); return 1; }
static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct gost_mac_pmeth_data *data = (struct gost_mac_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); switch (type) { case EVP_PKEY_CTRL_MD: { if (EVP_MD_type((const EVP_MD *)p2) != NID_id_Gost28147_89_MAC) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_DIGEST_TYPE); return 0; } data->md = (EVP_MD *)p2; return 1; } break; case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: case EVP_PKEY_CTRL_PKCS7_SIGN: return 1; case EVP_PKEY_CTRL_SET_MAC_KEY: if (p1 != 32) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH); return 0; } memcpy(data->key,p2,32); data->key_set = 1; return 1; case EVP_PKEY_CTRL_DIGESTINIT: { EVP_MD_CTX *mctx = p2; void *key; if (!data->key_set) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (!pkey) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET); return 0; } key = EVP_PKEY_get0(pkey); if (!key) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET); return 0; } } else { key = &(data->key); } return mctx->digest->md_ctrl(mctx,EVP_MD_CTRL_SET_KEY,32,key); } } return -2; }
soter_status_t soter_asym_ka_gen_key(soter_asym_ka_t* asym_ka_ctx) { EVP_PKEY* pkey; EC_KEY* ec; if (!asym_ka_ctx) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_CTX_get0_pkey(asym_ka_ctx->pkey_ctx); if (!pkey) { return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_EC != EVP_PKEY_id(pkey)) { return SOTER_INVALID_PARAMETER; } ec = EVP_PKEY_get0_EC_KEY(pkey); if (NULL == ec) { return SOTER_INVALID_PARAMETER; } if (1 == EC_KEY_generate_key(ec)) { return SOTER_SUCCESS; } return SOTER_FAIL; }
/* Allocates new gost_pmeth_data structure and assigns it as data */ static int pkey_gost_init(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); data = OPENSSL_malloc(sizeof(*data)); if (!data) return 0; memset(data, 0, sizeof(*data)); if (pkey && EVP_PKEY_get0(pkey)) { switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_2001: case NID_id_GostR3410_2012_256: case NID_id_GostR3410_2012_512: { const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)); if (group != NULL) { data->sign_param_nid = EC_GROUP_get_curve_name(group); break; } /* else */ } default: OPENSSL_free(data); return 0; } } EVP_PKEY_CTX_set_data(ctx, data); return 1; }
/* rsa_ctx_to_pss converts EVP_PKEY_CTX in PSS mode into corresponding * algorithm parameter, suitable for setting as an AlgorithmIdentifier. */ static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) { const EVP_MD *sigmd, *mgf1md; RSA_PSS_PARAMS *pss = NULL; ASN1_STRING *os = NULL; EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx); int saltlen, rv = 0; if (!EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) || !EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) || !EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) { goto err; } if (saltlen == -1) { saltlen = EVP_MD_size(sigmd); } else if (saltlen == -2) { saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2; if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) { saltlen--; } } else { goto err; } pss = RSA_PSS_PARAMS_new(); if (!pss) { goto err; } if (saltlen != 20) { pss->saltLength = ASN1_INTEGER_new(); if (!pss->saltLength || !ASN1_INTEGER_set(pss->saltLength, saltlen)) { goto err; } } if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) || !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) { goto err; } /* Finally create string with pss parameter encoding. */ if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) { goto err; } rv = 1; err: if (pss) { RSA_PSS_PARAMS_free(pss); } if (rv) { return os; } if (os) { ASN1_STRING_free(os); } return NULL; }
static int pkey_gost_ec_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbs_len) { DSA_SIG *unpacked_sig = NULL; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); int order = 0; if (!siglen) return 0; if (!pkey) return 0; switch (EVP_PKEY_base_id(pkey)) { case NID_id_GostR3410_2001: case NID_id_GostR3410_2012_256: order = 64; break; case NID_id_GostR3410_2012_512: order = 128; break; default: return 0; } if (!sig) { *siglen = order; return 1; } unpacked_sig = gost_ec_sign(tbs, tbs_len, EVP_PKEY_get0(pkey)); if (!unpacked_sig) { return 0; } return pack_sign_cp(unpacked_sig, order / 2, sig, siglen); }
static int ossl_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); EVP_PKEY *pk; ASN1_OCTET_STRING *key; switch (type) { case EVP_PKEY_CTRL_SET_MAC_KEY: if ((!p2 && p1 > 0) || (p1 < -1)) return 0; if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) return 0; break; case EVP_PKEY_CTRL_MD: hctx->md = p2; break; case EVP_PKEY_CTRL_DIGESTINIT: pk = EVP_PKEY_CTX_get0_pkey(ctx); key = EVP_PKEY_get0(pk); if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, NULL)) return 0; break; default: return -2; } return 1; }
static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) { ASN1_OBJECT *aoid; int atype; void *aval; ASN1_INTEGER *public_key = NULL; int rv = 0; EVP_PKEY *pkpeer = NULL, *pk = NULL; DH *dhpeer = NULL; const unsigned char *p; int plen; X509_ALGOR_get0(&aoid, &atype, &aval, alg); if (OBJ_obj2nid(aoid) != NID_dhpublicnumber) goto err; /* Only absent parameters allowed in RFC XXXX */ if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL) goto err; pk = EVP_PKEY_CTX_get0_pkey(pctx); if (!pk) goto err; if (pk->type != EVP_PKEY_DHX) goto err; /* Get parameters from parent key */ dhpeer = DHparams_dup(pk->pkey.dh); /* We have parameters now set public key */ plen = ASN1_STRING_length(pubkey); p = ASN1_STRING_data(pubkey); if (!p || !plen) goto err; if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, plen))) { DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR); goto err; } /* We have parameters now set public key */ if (!(dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) { DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR); goto err; } pkpeer = EVP_PKEY_new(); if (!pkpeer) goto err; EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer); dhpeer = NULL; if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) rv = 1; err: if (public_key) ASN1_INTEGER_free(public_key); if (pkpeer) EVP_PKEY_free(pkpeer); if (dhpeer) DH_free(dhpeer); return rv; }
/* * EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-2001 * algorithm */ int pkey_gost2001_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { /* * Public key of peer in the ctx field peerkey Our private key in the ctx * pkey ukm is in the algorithm specific context data */ EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); if (!data->shared_ukm) { GOSTerr(GOST_F_PKEY_GOST2001_DERIVE, GOST_R_UKM_NOT_SET); return 0; } if (key == NULL) { *keylen = 32; return 32; } *keylen = VKO_compute_key(key, 32, EC_KEY_get0_public_key(EVP_PKEY_get0(peer_key)), (EC_KEY *)EVP_PKEY_get0(my_key), data->shared_ukm); return 1; }
soter_status_t soter_ec_gen_key(EVP_PKEY_CTX *pkey_ctx) { EVP_PKEY *pkey; EC_KEY *ec=NULL; if (!pkey_ctx){ return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_CTX_get0_pkey(pkey_ctx); if (!pkey){ return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_EC != EVP_PKEY_id(pkey)){ return SOTER_INVALID_PARAMETER; } /* ec = EVP_PKEY_get0_EC_KEY(pkey); */ /* if (NULL == ec){ */ /* return SOTER_INVALID_PARAMETER; */ /* } */ ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if(!ec){ return SOTER_ENGINE_FAIL; } if (!EC_KEY_generate_key(ec)){ return SOTER_ENGINE_FAIL; } if(!EVP_PKEY_set1_EC_KEY(pkey, ec)){ return SOTER_ENGINE_FAIL; } EC_KEY_free(ec); return SOTER_SUCCESS; }
int pkey_gost94_derive(EVP_PKEY_CTX *ctx,unsigned char *key,size_t *keylen) { EVP_PKEY *pubk = EVP_PKEY_CTX_get0_peerkey(ctx); EVP_PKEY *mykey = EVP_PKEY_CTX_get0_pkey(ctx); *keylen = 32; if (key == NULL) return 1; return make_cp_exchange_key(gost_get0_priv_key(mykey), pubk, key); }
static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) { ASN1_OBJECT *aoid; int atype; void *aval; int rv = 0; EVP_PKEY *pkpeer = NULL; EC_KEY *ecpeer = NULL; const unsigned char *p; int plen; X509_ALGOR_get0(&aoid, &atype, &aval, alg); if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) goto err; /* If absent parameters get group from main key */ if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) { const EC_GROUP *grp; EVP_PKEY *pk; pk = EVP_PKEY_CTX_get0_pkey(pctx); if (!pk) goto err; grp = EC_KEY_get0_group(pk->pkey.ec); ecpeer = EC_KEY_new(); if (!ecpeer) goto err; if (!EC_KEY_set_group(ecpeer, grp)) goto err; } else { ecpeer = eckey_type2param(atype, aval); if (!ecpeer) goto err; } /* We have parameters now set public key */ plen = ASN1_STRING_length(pubkey); p = ASN1_STRING_data(pubkey); if (!p || !plen) goto err; if (!o2i_ECPublicKey(&ecpeer, &p, plen)) goto err; pkpeer = EVP_PKEY_new(); if (!pkpeer) goto err; EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer); if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) rv = 1; err: if (ecpeer) EC_KEY_free(ecpeer); if (pkpeer) EVP_PKEY_free(pkpeer); return rv; }
int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { const EVP_MD *sigmd, *mgf1md; int saltlen; if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) || !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) || !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) { return 0; } EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx); if (saltlen == -1) { saltlen = EVP_MD_size(sigmd); } else if (saltlen == -2) { saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2; if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) { saltlen--; } } else { return 0; } int ret = 0; ASN1_STRING *os = NULL; RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new(); if (!pss) { goto err; } if (saltlen != 20) { pss->saltLength = ASN1_INTEGER_new(); if (!pss->saltLength || !ASN1_INTEGER_set(pss->saltLength, saltlen)) { goto err; } } if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) || !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) { goto err; } /* Finally create string with pss parameter encoding. */ if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) { goto err; } X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os); os = NULL; ret = 1; err: RSA_PSS_PARAMS_free(pss); ASN1_STRING_free(os); return ret; }
static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbs_len) { int ok = 0; EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); DSA_SIG *s=unpack_cp_signature(sig,siglen); if (!s) return 0; if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); DSA_SIG_free(s); return ok; }
static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); switch (type) { case EVP_PKEY_CTRL_MD: if (EVP_MD_type(p2) != NID_id_Gost28147_89_MAC) { GOSTerror(GOST_R_INVALID_DIGEST_TYPE); return 0; } data->md = p2; return 1; case EVP_PKEY_CTRL_SET_MAC_KEY: if (p1 != 32) { GOSTerror(GOST_R_INVALID_MAC_KEY_LENGTH); return 0; } memcpy(data->key, p2, 32); data->key_set = 1; return 1; case EVP_PKEY_CTRL_DIGESTINIT: { EVP_MD_CTX *mctx = p2; void *key; if (!data->key_set) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (pkey == NULL) { GOSTerror(GOST_R_MAC_KEY_NOT_SET); return 0; } key = EVP_PKEY_get0(pkey); if (key == NULL) { GOSTerror(GOST_R_MAC_KEY_NOT_SET); return 0; } } else { key = &(data->key); } if (mctx->digest->md_ctrl == NULL) return 0; return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32 * 8, key); } } return -2; }
static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) { MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); ASN1_OCTET_STRING *key = NULL; int rv = 1; /* * For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that * gets the key passed as an ASN.1 OCTET STRING, we set the key here, * as this may be only time it's set during a DigestSign. * * MACs that pass around the key in form of EVP_MAC_CTX are setting * the key through other mechanisms. (this is only CMAC for now) */ int set_key = hctx->type == MAC_TYPE_RAW && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0; if (set_key) { if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx)) != EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx))) return 0; key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx)); if (key == NULL) return 0; } /* Some MACs don't support this control... that's fine */ EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS, EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT)); EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); EVP_MD_CTX_set_update_fn(mctx, int_update); if (set_key) rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data, key->length); return rv > 0; }
soter_status_t soter_asym_ka_cleanup(soter_asym_ka_t* asym_ka_ctx) { if (!asym_ka_ctx) { return SOTER_INVALID_PARAMETER; } if (asym_ka_ctx->pkey_ctx) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(asym_ka_ctx->pkey_ctx); if(pkey)EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(asym_ka_ctx->pkey_ctx); } return SOTER_SUCCESS; }
//We can control the state of our engine by commands static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { struct te_mac_pmeth_data *data = (struct te_mac_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); switch (type) { case EVP_PKEY_CTRL_MD: if (EVP_MD_type((const EVP_MD *)p2) != NID_hmac_sha1) { printf("Error: unsupported digest type\n"); return 0; } data->md = (EVP_MD*)p2; return 1; case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: case EVP_PKEY_CTRL_PKCS7_SIGN: return 1; case EVP_PKEY_CTRL_SET_MAC_KEY: //here we can insert pkey extraction printf("Got set user id command: %s\n", (char*)p2); //or save user id for further operations if(strcmp((char*)p2, "123")) { printf("Error: unknown user (id = %s)\n", (char*)p2); return 0; } memcpy(data->uid, p2, p1); memcpy(data->key, "user_123_key\0", 13); data->key_ln = 12; data->key_set = 1; return 1; case EVP_PKEY_CTRL_DIGESTINIT: { //this request runs in different context (for unknown reason) printf("Got digest init command\n"); //but has the key that we have installed in keygen request void *key = 0; //in this request we must transfer the key into digest context int keyln = 0; //so digest must support control commands if(!data->key_set) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (!pkey) { printf("Error: unable to set key\n"); return 0; } key = EVP_PKEY_get0(pkey); if (!key) { printf("Error: unable to set key\n"); return 0; } keyln = strlen((char *)key); //it's so dangerous } else { key = &(data->key); keyln = data->key_ln; } return ((EVP_MD_CTX*)p2)->digest->md_ctrl((EVP_MD_CTX*)p2, EVP_MD_CTRL_SET_KEY, keyln, key); } } return -2; }
soter_status_t soter_rsa_key_pair_gen_export_key(soter_rsa_key_pair_gen_t* ctx, void* key, size_t* key_length, bool isprivate){ EVP_PKEY *pkey; SOTER_CHECK_PARAM(ctx); pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx); SOTER_CHECK_PARAM(pkey); SOTER_CHECK_PARAM(EVP_PKEY_RSA == EVP_PKEY_id(pkey)); if (isprivate) { return soter_engine_specific_to_rsa_priv_key((const soter_engine_specific_rsa_key_t *)pkey, (soter_container_hdr_t *)key, key_length); } else { return soter_engine_specific_to_rsa_pub_key((const soter_engine_specific_rsa_key_t *)pkey, (soter_container_hdr_t *)key, key_length); } }
soter_status_t soter_sign_final_rsa_pss_pkcs8(soter_sign_ctx_t* ctx, void* signature, size_t* signature_length) { EVP_PKEY* pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx); if (!pkey) { return SOTER_INVALID_PARAMETER; } if ((*signature_length) < (size_t)EVP_PKEY_size(pkey)) { (*signature_length) = (size_t)EVP_PKEY_size(pkey); return SOTER_BUFFER_TOO_SMALL; } if (!EVP_DigestSignFinal(ctx->md_ctx, signature, signature_length)) { return SOTER_FAIL; } return SOTER_SUCCESS; }
soter_status_t soter_rsa_export_key(soter_sign_ctx_t* ctx, void* key, size_t* key_length, bool isprivate) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx); if (!pkey){ return SOTER_INVALID_PARAMETER; } if(isprivate) { return soter_engine_specific_to_rsa_priv_key((const soter_engine_specific_rsa_key_t *)pkey, (soter_container_hdr_t *)key, key_length); } else { return soter_engine_specific_to_rsa_pub_key((const soter_engine_specific_rsa_key_t *)pkey, (soter_container_hdr_t *)key, key_length); } }
soter_status_t soter_sign_final_ecdsa_none_pkcs8(soter_sign_ctx_t* ctx, void* signature, size_t *signature_length) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx); if (!pkey && EVP_PKEY_base_id(pkey)!=EVP_PKEY_EC){ return SOTER_INVALID_PARAMETER; } /* TODO: need review */ soter_status_t res = SOTER_SUCCESS; if(!signature || (*signature_length)<(size_t)EVP_PKEY_size(pkey)){ (*signature_length)=(size_t)EVP_PKEY_size(pkey); res = SOTER_BUFFER_TOO_SMALL; } else { if(EVP_DigestSignFinal(ctx->md_ctx, signature, signature_length)!=1) res = SOTER_INVALID_SIGNATURE; } return res; }
soter_status_t soter_verify_cleanup_rsa_pss_pkcs8(soter_sign_ctx_t* ctx) { if(!ctx){ return SOTER_INVALID_PARAMETER; } if(ctx->pkey_ctx){ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx); if(pkey)EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx->pkey_ctx); ctx->pkey_ctx=NULL; } if(ctx->md_ctx){ EVP_MD_CTX_destroy(ctx->md_ctx); ctx->md_ctx=NULL; } return SOTER_SUCCESS; }
soter_status_t soter_verify_final_rsa_pss_pkcs8(soter_sign_ctx_t* ctx, const void* signature, const size_t signature_length) { if (!ctx){ return SOTER_INVALID_PARAMETER; } EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx); if (!pkey){ return SOTER_INVALID_PARAMETER; } if(signature_length!=EVP_PKEY_size(pkey)){ return SOTER_FAIL; } if(!EVP_DigestVerifyFinal(ctx->md_ctx, (unsigned char*)signature, signature_length)){ return SOTER_FAIL; } return SOTER_SUCCESS; }
static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbs_len) { int ok = 0; EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); DSA_SIG *s=unpack_cp_signature(sig,siglen); if (!s) return 0; #ifdef DEBUG_SIGN fprintf(stderr,"R="); BN_print_fp(stderr,s->r); fprintf(stderr,"\nS="); BN_print_fp(stderr,s->s); fprintf(stderr,"\n"); #endif if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); DSA_SIG_free(s); return ok; }
static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbs_len) { DSA_SIG *unpacked_sig=NULL; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (!siglen) return 0; if (!sig) { *siglen= 64; /* better to check size of curve order*/ return 1; } unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey)); if (!unpacked_sig) { return 0; } return pack_sign_cp(unpacked_sig,32,sig,siglen); }