static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (!value) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); return 0; } if (!strcmp(type, "rsa_padding_mode")) { int pm; if (!strcmp(value, "pkcs1")) pm = RSA_PKCS1_PADDING; else if (!strcmp(value, "sslv23")) pm = RSA_SSLV23_PADDING; else if (!strcmp(value, "none")) pm = RSA_NO_PADDING; else if (!strcmp(value, "oeap")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "x931")) pm = RSA_X931_PADDING; else if (!strcmp(value, "pss")) pm = RSA_PKCS1_PSS_PADDING; else { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); return -2; } return EVP_PKEY_CTX_set_rsa_padding(ctx, pm); } if (!strcmp(type, "rsa_pss_saltlen")) { int saltlen; saltlen = atoi(value); return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); } if (!strcmp(type, "rsa_keygen_bits")) { int nbits; nbits = atoi(value); return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); } if (!strcmp(type, "rsa_keygen_pubexp")) { int ret; BIGNUM *pubexp = NULL; if (!BN_asc2bn(&pubexp, value)) return 0; ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp); if (ret <= 0) BN_free(pubexp); return ret; } return -2; }
static gboolean verify_signature (const uint8_t *hash, const uint8_t *signature, EVP_PKEY *pubkey, GError **error) { EVP_PKEY_CTX *pkey_ctx = EVP_PKEY_CTX_new (pubkey, NULL); gboolean ret = TRUE; if (pkey_ctx == NULL) { g_set_error_literal (error, CRYPT_ERROR, CRYPT_ERROR_INIT, "Error allocating pkey context"); ret = FALSE; } else { if (EVP_PKEY_verify_init (pkey_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_padding (pkey_ctx, RSA_PKCS1_PADDING) <= 0 || EVP_PKEY_CTX_set_signature_md (pkey_ctx, EVP_sha256 ()) <= 0) { g_set_error_literal (error, CRYPT_ERROR, CRYPT_ERROR_INIT, "Error initialising pkey context"); ret = FALSE; } else { int validate_ret = EVP_PKEY_verify (pkey_ctx, signature, SIGNATURE_SIZE, hash, SHA256_DIGEST_LENGTH); if (validate_ret == 0) { g_set_error_literal (error, CRYPT_ERROR, CRYPT_ERROR_INVALID_SIGNATURE, "Signature is invalid"); ret = FALSE; } else if (validate_ret != 1) { g_set_error_literal (error, CRYPT_ERROR, CRYPT_ERROR_VERIFY, "Error verifying signature"); ret = FALSE; } } EVP_PKEY_CTX_free (pkey_ctx); } return ret; }
//The partner verification function to the above signing function. Similar problem int verify_signed_data(char *data, size_t data_len, unsigned char *orig_sig, size_t sig_len, EVP_PKEY *key) { EVP_PKEY_CTX *ctx; ctx = EVP_PKEY_CTX_new(key, NULL); EVP_PKEY_verify_init(ctx); EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()); return EVP_PKEY_verify(ctx, orig_sig, sig_len, data, data_len); }
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; }
static EVP_MD_CTX * setup(jose_cfg_t *cfg, const json_t *jwk, const json_t *sig, const char *alg, init_t *func) { openssl_auto(EVP_PKEY) *key = NULL; EVP_PKEY_CTX *epc = NULL; const EVP_MD *md = NULL; EVP_MD_CTX *emc = NULL; const RSA *rsa = NULL; int slen = 0; int pad = 0; switch (str2enum(alg, NAMES, NULL)) { case 0: md = EVP_sha256(); pad = RSA_PKCS1_PADDING; break; case 1: md = EVP_sha384(); pad = RSA_PKCS1_PADDING; break; case 2: md = EVP_sha512(); pad = RSA_PKCS1_PADDING; break; case 3: md = EVP_sha256(); pad = RSA_PKCS1_PSS_PADDING; slen = -1; break; case 4: md = EVP_sha384(); pad = RSA_PKCS1_PSS_PADDING; slen = -1; break; case 5: md = EVP_sha512(); pad = RSA_PKCS1_PSS_PADDING; slen = -1; break; default: return NULL; } key = jose_openssl_jwk_to_EVP_PKEY(cfg, jwk); if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA) return NULL; /* Don't use small keys. RFC 7518 3.3 */ rsa = EVP_PKEY_get0_RSA(key); if (!rsa) return NULL; if (RSA_size(rsa) < 2048 / 8) return NULL; emc = EVP_MD_CTX_new(); if (!emc) return NULL; if (func(emc, &epc, md, NULL, key) <= 0) goto error; if (EVP_PKEY_CTX_set_rsa_padding(epc, pad) <= 0) goto error; if (slen != 0) { if (EVP_PKEY_CTX_set_rsa_pss_saltlen(epc, slen) <= 0) goto error; } return emc; error: EVP_MD_CTX_free(emc); return NULL; }
int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); /* Decode PSS parameters */ int ret = 0; X509_ALGOR *maskHash; RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); goto err; } const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm); if (mgf1md == NULL || md == NULL) { goto err; } int saltlen = 20; if (pss->saltLength != NULL) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); goto err; } } /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); goto err; } EVP_PKEY_CTX *pctx; if (!EVP_DigestVerifyInit(ctx, &pctx, md, NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, saltlen) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md)) { goto err; } ret = 1; err: RSA_PSS_PARAMS_free(pss); X509_ALGOR_free(maskHash); return ret; }
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg); if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS); goto err; } /* We have all parameters now set up context */ if (pkey) { if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; } else { const EVP_MD *checkmd; if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) goto err; if (EVP_MD_type(md) != EVP_MD_type(checkmd)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH); goto err; } } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_PSS_PARAMS_free(pss); return rv; }
//Experimental function for signing data using a public key. Couldn't get it //complete working. Seems to have problem with XDRed things unsigned char *sign_data(char *data, size_t len, EVP_PKEY* key, int *sig_len) { EVP_PKEY_CTX *ctx; ctx = EVP_PKEY_CTX_new(key, NULL); EVP_PKEY_sign_init(ctx); EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()); EVP_PKEY_sign(ctx, NULL, sig_len, data, len); //determines the sig_len unsigned char * sig = OPENSSL_malloc(*sig_len); if(EVP_PKEY_sign(ctx, sig, sig_len, data, len <= 0)) { ssl_error("PKEY SIGN"); sig = NULL; } return sig; }
static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md, const uint8_t *in, size_t in_len) { EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); *out_len = max_out; EVP_PKEY_CTX *pctx; int ret = EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) && EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) && EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) && EVP_DigestSignUpdate(&ctx, in, in_len) && EVP_DigestSignFinal(&ctx, out, out_len); EVP_MD_CTX_cleanup(&ctx); return ret; }
static LUA_FUNCTION(openssl_pkey_decrypt) { size_t dlen = 0; EVP_PKEY *pkey = CHECK_OBJECT(1, EVP_PKEY, "openssl.evp_pkey"); const char *data = luaL_checklstring(L, 2, &dlen); int padding = auxiliar_checkoption(L, 3, "pkcs1", sPadding, iPadding); size_t clen = EVP_PKEY_size(pkey); EVP_PKEY_CTX *ctx = NULL; int ret = 0; if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA2) { luaL_argerror(L, 2, "EVP_PKEY must be of type RSA or RSA2"); return ret; } if (openssl_pkey_is_private(pkey)) { ctx = EVP_PKEY_CTX_new(pkey, pkey->engine); if (EVP_PKEY_decrypt_init(ctx) == 1) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 1) { byte* buf = malloc(clen); if (EVP_PKEY_decrypt(ctx, buf, &clen, (const unsigned char*)data, dlen) == 1) { lua_pushlstring(L, (const char*)buf, clen); ret = 1; } else ret = openssl_pushresult(L, 0); free(buf); } else ret = openssl_pushresult(L, 0); } else ret = openssl_pushresult(L, 0); EVP_PKEY_CTX_free(ctx); } else { luaL_argerror(L, 2, "EVP_PKEY must be private key"); } return ret; }
static int test_EVP_DigestSignAlgorithm(void) { int ret = 0; EVP_PKEY *pkey = NULL; EVP_MD_CTX md_ctx; EVP_PKEY_CTX *pkey_ctx; EVP_MD_CTX_init(&md_ctx); pkey = load_example_rsa_key(); if (pkey == NULL) { goto out; } /* Test a simple AlgorithmIdentifier. */ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) || !test_algorithm_roundtrip(&md_ctx, pkey)) { fprintf(stderr, "RSA with SHA-256 failed\n"); goto out; } EVP_MD_CTX_cleanup(&md_ctx); EVP_MD_CTX_init(&md_ctx); /* Test RSA-PSS with custom parameters. */ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) || !test_algorithm_roundtrip(&md_ctx, pkey)) { fprintf(stderr, "RSA-PSS failed\n"); goto out; } ret = 1; out: if (!ret) { BIO_print_errors_fp(stderr); } EVP_MD_CTX_cleanup(&md_ctx); if (pkey) { EVP_PKEY_free(pkey); } return ret; }
SEXP PKI_sign(SEXP what, SEXP sKey, SEXP sMD, SEXP sPad) { SEXP res; EVP_PKEY *key; EVP_PKEY_CTX *ctx; int mdt, padt, r; size_t sl; if (TYPEOF(what) != RAWSXP) Rf_error("invalid payload to sign - must be a raw vector"); if (!inherits(sKey, "private.key")) Rf_error("key must be RSA private key"); PKI_init(); mdt = asInteger(sMD); padt = asInteger(sPad); key = (EVP_PKEY*) R_ExternalPtrAddr(sKey); if (!key) Rf_error("NULL key"); ctx = EVP_PKEY_CTX_new(key); if (!ctx || EVP_PKEY_sign_init(ctx) <= 0) Rf_error("%s", ERR_error_string(ERR_get_error(), NULL)); switch (padt) { case PKI_PKCS1: default: r = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); } if (r <= 0) Rf_error("%s", ERR_error_string(ERR_get_error(), NULL)); switch (mdt) { case PKI_MD5: r = EVP_PKEY_CTX_set_signature_md(ctx, EVP_md5()); break; case PKI_SHA1: r = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()); break; default: case PKI_SHA256: r = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()); break; } if (r <= 0) Rf_error("%s", ERR_error_string(ERR_get_error(), NULL)); sl = sizeof(buf); if (EVP_PKEY_sign(ctx, buf, &sl, (const unsigned char*) RAW(what), LENGTH(what)) <= 0) Rf_error("%s", ERR_error_string(ERR_get_error(), NULL)); res = allocVector(RAWSXP, sl); memcpy(RAW(res), buf, sl); EVP_PKEY_CTX_free(ctx); return res; }
static int ssl_verify_rsa_pss(SSL *ssl, const uint8_t *signature, size_t signature_len, const EVP_MD *md, EVP_PKEY *pkey, const uint8_t *in, size_t in_len) { if (pkey->type != EVP_PKEY_RSA) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); return 0; } EVP_MD_CTX md_ctx; EVP_MD_CTX_init(&md_ctx); EVP_PKEY_CTX *pctx; int ret = EVP_DigestVerifyInit(&md_ctx, &pctx, md, NULL, pkey) && EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) && EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) && EVP_DigestVerifyUpdate(&md_ctx, in, in_len) && EVP_DigestVerifyFinal(&md_ctx, signature, signature_len); EVP_MD_CTX_cleanup(&md_ctx); return ret; }
static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, X509_ALGOR *sigalg, ASN1_BIT_STRING *sig, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; EVP_PKEY_CTX *pkctx; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_PSS_PARAMETERS); goto err; } /* Check mask and lookup mask hash algorithm */ if (pss->maskGenAlgorithm) { if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) != NID_mgf1) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_ALGORITHM); goto err; } if (!maskHash) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_PARAMETER); goto err; } mgf1md = EVP_get_digestbyobj(maskHash->algorithm); if (mgf1md == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_MASK_DIGEST); goto err; } } else mgf1md = EVP_sha1(); if (pss->hashAlgorithm) { md = EVP_get_digestbyobj(pss->hashAlgorithm->algorithm); if (md == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_PSS_DIGEST); goto err; } } else md = EVP_sha1(); if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_SALT_LENGTH); goto err; } } else saltlen = 20; /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_TRAILER); goto err; } /* We have all parameters now set up context */ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 2; err: RSA_PSS_PARAMS_free(pss); if (maskHash) X509_ALGOR_free(maskHash); return rv; }
static bool alg_wrap_wrp(const jose_hook_alg_t *alg, jose_cfg_t *cfg, json_t *jwe, json_t *rcp, const json_t *jwk, json_t *cek) { openssl_auto(EVP_PKEY_CTX) *epc = NULL; openssl_auto(EVP_PKEY) *key = NULL; const EVP_MD *md = NULL; const RSA *rsa = NULL; uint8_t *pt = NULL; uint8_t *ct = NULL; bool ret = false; size_t ptl = 0; size_t ctl = 0; int tmp = 0; int pad = 0; if (!json_object_get(cek, "k") && !jose_jwk_gen(cfg, cek)) return false; switch (str2enum(alg->name, NAMES, NULL)) { case 0: pad = RSA_PKCS1_PADDING; tmp = 11; md = EVP_sha1(); break; case 1: pad = RSA_PKCS1_OAEP_PADDING; tmp = 41; md = EVP_sha1(); break; case 2: pad = RSA_PKCS1_OAEP_PADDING; tmp = 41; md = EVP_sha256(); break; default: return false; } key = jose_openssl_jwk_to_EVP_PKEY(cfg, jwk); if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA) return false; ptl = jose_b64_dec(json_object_get(cek, "k"), NULL, 0); if (ptl == SIZE_MAX) return false; rsa = EVP_PKEY_get0_RSA(key); if (!rsa) return false; if ((int) ptl >= RSA_size(rsa) - tmp) return false; epc = EVP_PKEY_CTX_new(key, NULL); if (!epc) return false; if (EVP_PKEY_encrypt_init(epc) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_padding(epc, pad) <= 0) return false; if (pad == RSA_PKCS1_OAEP_PADDING) { if (EVP_PKEY_CTX_set_rsa_oaep_md(epc, md) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_mgf1_md(epc, md) <= 0) return false; } pt = malloc(ptl); if (!pt) return false; if (jose_b64_dec(json_object_get(cek, "k"), pt, ptl) != ptl) goto egress; if (EVP_PKEY_encrypt(epc, NULL, &ctl, pt, ptl) <= 0) goto egress; ct = malloc(ctl); if (!ct) goto egress; if (EVP_PKEY_encrypt(epc, ct, &ctl, pt, ptl) <= 0) goto egress; if (json_object_set_new(rcp, "encrypted_key", jose_b64_enc(ct, ctl)) < 0) goto egress; ret = add_entity(jwe, rcp, "recipients", "header", "encrypted_key", NULL); egress: if (pt) { OPENSSL_cleanse(pt, ptl); free(pt); } free(ct); return ret; }
static bool alg_wrap_unw(const jose_hook_alg_t *alg, jose_cfg_t *cfg, const json_t *jwe, const json_t *rcp, const json_t *jwk, json_t *cek) { openssl_auto(EVP_PKEY_CTX) *epc = NULL; openssl_auto(EVP_PKEY) *key = NULL; const uint8_t *tt = NULL; const EVP_MD *md = NULL; uint8_t *ct = NULL; uint8_t *pt = NULL; uint8_t *rt = NULL; bool ret = false; size_t ctl = 0; size_t ptl = 0; size_t rtl = 0; size_t ttl = 0; int pad = 0; switch (str2enum(alg->name, NAMES, NULL)) { case 0: pad = RSA_PKCS1_PADDING; md = EVP_sha1(); break; case 1: pad = RSA_PKCS1_OAEP_PADDING; md = EVP_sha1(); break; case 2: pad = RSA_PKCS1_OAEP_PADDING; md = EVP_sha256(); break; default: return false; } key = jose_openssl_jwk_to_EVP_PKEY(cfg, jwk); if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA) goto egress; ctl = jose_b64_dec(json_object_get(rcp, "encrypted_key"), NULL, 0); if (ctl == SIZE_MAX) goto egress; ct = malloc(ctl); if (!ct) goto egress; if (jose_b64_dec(json_object_get(rcp, "encrypted_key"), ct, ctl) != ctl) goto egress; ptl = ctl; pt = malloc(ptl); if (!pt) goto egress; epc = EVP_PKEY_CTX_new(key, NULL); if (!epc) goto egress; if (EVP_PKEY_decrypt_init(epc) <= 0) goto egress; if (EVP_PKEY_CTX_set_rsa_padding(epc, pad) <= 0) goto egress; if (pad == RSA_PKCS1_OAEP_PADDING) { if (EVP_PKEY_CTX_set_rsa_oaep_md(epc, md) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_mgf1_md(epc, md) <= 0) goto egress; } /* Handle MMA Attack as prescribed by RFC 3218, always generate a * random buffer of appropriate length so that the same operations * are performed whether decrypt succeeds or not, in an attempt to * foil timing attacks */ rtl = ptl; rt = malloc(rtl); if (!rt) goto egress; if (RAND_bytes(rt, rtl) <= 0) goto egress; ret |= EVP_PKEY_decrypt(epc, pt, &ptl, ct, ctl) > 0; ttl = ret ? ptl : rtl; tt = ret ? pt : rt; ret |= pad == RSA_PKCS1_PADDING; if (json_object_set_new(cek, "k", jose_b64_enc(tt, ttl)) < 0) ret = false; egress: if (pt) { OPENSSL_cleanse(pt, ptl); free(pt); } if (rt) { OPENSSL_cleanse(rt, rtl); free(rt); } free(ct); return ret; }
static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo) { int rc, ret; EVP_PKEY_CTX *pkey_ctx = NULL; struct pgpDigSigRSA_s *sig = pgpsig->data; void *padded_sig = NULL; struct pgpDigKeyRSA_s *key = pgpkey->data; if (!constructRSASigningKey(key)) { rc = 1; goto done; } pkey_ctx = EVP_PKEY_CTX_new(key->evp_pkey, NULL); if (!pkey_ctx) { rc = 1; goto done; } ret = EVP_PKEY_verify_init(pkey_ctx); if (ret < 0) { rc = 1; goto done; } ret = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING); if (ret < 0) { rc = 1; goto done; } ret = EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo)); if (ret < 0) { rc = 1; goto done; } int pkey_len = EVP_PKEY_size(key->evp_pkey); padded_sig = xcalloc(1, pkey_len); if (!BN_bn2binpad(sig->bn, padded_sig, pkey_len)) { rc = 1; goto done; } ret = EVP_PKEY_verify(pkey_ctx, padded_sig, pkey_len, hash, hashlen); if (ret == 1) { /* Success */ rc = 0; } else { /* Failure */ rc = 1; } done: EVP_PKEY_CTX_free(pkey_ctx); free(padded_sig); return rc; }
DWORD VmDirVerifyRSASignature( EVP_PKEY* pPubKey, const EVP_MD* digestMethod, const unsigned char* pData, size_t dataSize, const unsigned char* pSignature, size_t signatureSize, PBOOLEAN pVerified ) { DWORD dwError = 0; int retVal = 0; unsigned char* pMd = NULL; size_t mdSize = 0; EVP_PKEY_CTX* pPubKeyCtx = NULL; if (!pPubKey || !digestMethod || !pData || !pData || !pVerified) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } dwError = VmDirComputeMessageDigest(digestMethod, pData, dataSize, &pMd, &mdSize); BAIL_ON_VMDIR_ERROR(dwError); pPubKeyCtx = EVP_PKEY_CTX_new(pPubKey, NULL); if (!pPubKeyCtx) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_CTX_new returned NULL", __FUNCTION__); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_verify_init(pPubKeyCtx); if (retVal <= 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_verify_init returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_CTX_set_rsa_padding(pPubKeyCtx, RSA_PKCS1_PADDING); if (retVal <= 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_CTX_set_rsa_padding returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_CTX_set_signature_md(pPubKeyCtx, digestMethod); if (retVal <= 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_CTX_set_signature_md returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_verify(pPubKeyCtx, pSignature, signatureSize, pMd, mdSize); if (retVal == 1) { *pVerified = TRUE; } else if (retVal == 0) { *pVerified = FALSE; } else { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_verify returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } cleanup: VMDIR_SAFE_FREE_MEMORY(pMd); EVP_PKEY_CTX_free(pPubKeyCtx); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed with error (%d)", __FUNCTION__, dwError); goto cleanup; }
CK_RV PKCS11_Encryption_OpenSSL::InitHelper(Cryptoki_Session_Context* pSessionCtx, CK_MECHANISM_PTR pEncryptMech, CK_OBJECT_HANDLE hKey, BOOL isEncrypt) { OPENSSL_HEADER(); OpenSSLEncryptData* pEnc; const EVP_CIPHER* pCipher; int padding = 0; if( pSessionCtx == NULL) return CKR_SESSION_CLOSED; if( isEncrypt && pSessionCtx->EncryptionCtx != NULL) return CKR_SESSION_PARALLEL_NOT_SUPPORTED; if(!isEncrypt && pSessionCtx->DecryptionCtx != NULL) return CKR_SESSION_PARALLEL_NOT_SUPPORTED; pEnc = (OpenSSLEncryptData*)TINYCLR_SSL_MALLOC(sizeof(*pEnc)); if(pEnc == NULL) return CKR_DEVICE_MEMORY; TINYCLR_SSL_MEMSET(pEnc, 0, sizeof(*pEnc)); pEnc->Key = PKCS11_Keys_OpenSSL::GetKeyFromHandle(pSessionCtx, hKey, !isEncrypt); pEnc->IsSymmetric = TRUE; switch(pEncryptMech->mechanism) { case CKM_AES_CBC: case CKM_AES_CBC_PAD: switch(pEnc->Key->size) { case 128: pCipher = EVP_aes_128_cbc(); break; case 192: pCipher = EVP_aes_192_cbc(); break; case 256: pCipher = EVP_aes_256_cbc(); break; default: OPENSSL_SET_AND_LEAVE(CKR_MECHANISM_INVALID); } if(pEncryptMech->mechanism == CKM_AES_CBC_PAD) { padding = 1; } break; case CKM_AES_ECB: case CKM_AES_ECB_PAD: switch(pEnc->Key->size) { case 128: pCipher = EVP_aes_128_ecb(); break; case 192: pCipher = EVP_aes_192_ecb(); break; case 256: pCipher = EVP_aes_256_ecb(); break; default: OPENSSL_SET_AND_LEAVE(CKR_MECHANISM_INVALID); } if(pEncryptMech->mechanism == CKM_AES_ECB_PAD) { padding = 1; } break; case CKM_DES3_CBC: pCipher = EVP_des_ede3_cbc(); break; case CKM_DES3_CBC_PAD: pCipher = EVP_des_ede3_cbc(); padding = 1; break; case CKM_RSA_PKCS: pEnc->IsSymmetric= FALSE; padding = RSA_PKCS1_PADDING; break; default: OPENSSL_SET_AND_LEAVE(CKR_MECHANISM_INVALID); } if(pEnc->IsSymmetric) { if(pEncryptMech->ulParameterLen > 0 && pEncryptMech->ulParameterLen > 0) { memcpy(pEnc->IV, pEncryptMech->pParameter, pEncryptMech->ulParameterLen); } pEnc->Key->ctx = &pEnc->SymmetricCtx; if(isEncrypt) { OPENSSL_CHECKRESULT(EVP_EncryptInit(&pEnc->SymmetricCtx, pCipher, (const UINT8*)pEnc->Key->key, pEnc->IV)); } else { OPENSSL_CHECKRESULT(EVP_DecryptInit(&pEnc->SymmetricCtx, pCipher, (const UINT8*)pEnc->Key->key, pEnc->IV)); } OPENSSL_CHECKRESULT(EVP_CIPHER_CTX_set_padding(&pEnc->SymmetricCtx, padding)); } else { pEnc->Key->ctx = EVP_PKEY_CTX_new((EVP_PKEY*)pEnc->Key->key, NULL); if(isEncrypt) { OPENSSL_CHECKRESULT(EVP_PKEY_encrypt_init ((EVP_PKEY_CTX*)pEnc->Key->ctx )); OPENSSL_CHECKRESULT(EVP_PKEY_CTX_set_rsa_padding((EVP_PKEY_CTX*)pEnc->Key->ctx, padding)); } else { OPENSSL_CHECKRESULT(EVP_PKEY_decrypt_init ((EVP_PKEY_CTX*)pEnc->Key->ctx )); OPENSSL_CHECKRESULT(EVP_PKEY_CTX_set_rsa_padding((EVP_PKEY_CTX*)pEnc->Key->ctx, padding)); } } if(isEncrypt) pSessionCtx->EncryptionCtx = pEnc; else pSessionCtx->DecryptionCtx = pEnc; OPENSSL_CLEANUP(); if(retVal != CKR_OK && pEnc != NULL) { TINYCLR_SSL_FREE(pEnc); } OPENSSL_RETURN(); }
BUF_MEM * EAC_sign(int protocol, EVP_PKEY *key, const BUF_MEM *data) { BUF_MEM *signature = NULL, *signature_data = NULL, *plain_sig = NULL; EVP_PKEY_CTX *tmp_key_ctx = NULL; size_t len; const EVP_MD *md = eac_oid2md(protocol); int type; check((key && data), "Invalid arguments"); tmp_key_ctx = EVP_PKEY_CTX_new(key, NULL); if (!tmp_key_ctx || !md || EVP_PKEY_sign_init(tmp_key_ctx) <= 0 || EVP_PKEY_CTX_set_signature_md(tmp_key_ctx, md) <= 0) goto err; type = EVP_PKEY_base_id(key); if ( protocol == NID_id_TA_ECDSA_SHA_1 || protocol == NID_id_TA_ECDSA_SHA_224 || protocol == NID_id_TA_ECDSA_SHA_256 || protocol == NID_id_TA_ECDSA_SHA_384 || protocol == NID_id_TA_ECDSA_SHA_512) { if (!(type == EVP_PKEY_EC)) goto err; } else if (protocol == NID_id_TA_RSA_v1_5_SHA_1 || protocol == NID_id_TA_RSA_v1_5_SHA_256 || protocol == NID_id_TA_RSA_v1_5_SHA_512) { if (!(type == EVP_PKEY_RSA)) goto err; if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PADDING)) goto err; } else if (protocol == NID_id_TA_RSA_PSS_SHA_1 || protocol == NID_id_TA_RSA_PSS_SHA_256 || protocol == NID_id_TA_RSA_PSS_SHA_512) { if (!(type == EVP_PKEY_RSA)) goto err; if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PSS_PADDING)) goto err; } else { goto err; } /* EVP_PKEY_sign doesn't perform hashing (despite EVP_PKEY_CTX_set_signature_md). * Therefore we need to compute the hash ourself. */ signature_data = hash(md, NULL, NULL, data); if (!signature_data) goto err; /* Actual signature creation */ if (EVP_PKEY_sign(tmp_key_ctx, NULL, &len, (unsigned char*) signature_data->data, signature_data->length) <= 0) goto err; signature = BUF_MEM_create(len); if (!signature) goto err; if (EVP_PKEY_sign(tmp_key_ctx, (unsigned char *) signature->data, &signature->length, (unsigned char*) signature_data->data, signature_data->length) <= 0) goto err; /* EAC signatures are always in plain signature format for EC curves but * OpenSSL only creates X.509 format. Therefore we need to convert between * these formats. */ if ( protocol == NID_id_TA_ECDSA_SHA_1 || protocol == NID_id_TA_ECDSA_SHA_224 || protocol == NID_id_TA_ECDSA_SHA_256 || protocol == NID_id_TA_ECDSA_SHA_384 || protocol == NID_id_TA_ECDSA_SHA_512) { plain_sig = convert_to_plain_sig(signature); BUF_MEM_free(signature); signature = plain_sig; } err: if (tmp_key_ctx) EVP_PKEY_CTX_free(tmp_key_ctx); if (signature_data) BUF_MEM_free(signature_data); return signature; }
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { long lval; char *ep; if (!value) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); return 0; } if (!strcmp(type, "rsa_padding_mode")) { int pm; if (!strcmp(value, "pkcs1")) pm = RSA_PKCS1_PADDING; else if (!strcmp(value, "sslv23")) pm = RSA_SSLV23_PADDING; else if (!strcmp(value, "none")) pm = RSA_NO_PADDING; else if (!strcmp(value, "oeap")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "oaep")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "x931")) pm = RSA_X931_PADDING; else if (!strcmp(value, "pss")) pm = RSA_PKCS1_PSS_PADDING; else { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); return -2; } return EVP_PKEY_CTX_set_rsa_padding(ctx, pm); } if (!strcmp(type, "rsa_pss_saltlen")) { int saltlen; errno = 0; lval = strtol(value, &ep, 10); if (value[0] == '\0' || *ep != '\0') goto not_a_number; if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || (lval > INT_MAX || lval < INT_MIN)) goto out_of_range; saltlen = lval; return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); } if (!strcmp(type, "rsa_keygen_bits")) { int nbits; errno = 0; lval = strtol(value, &ep, 10); if (value[0] == '\0' || *ep != '\0') goto not_a_number; if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || (lval > INT_MAX || lval < INT_MIN)) goto out_of_range; nbits = lval; return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); } if (!strcmp(type, "rsa_keygen_pubexp")) { int ret; BIGNUM *pubexp = NULL; if (!BN_asc2bn(&pubexp, value)) return 0; ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp); if (ret <= 0) BN_free(pubexp); return ret; } not_a_number: out_of_range: return -2; }
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); if (!mgf1md) goto err; md = rsa_algor_to_md(pss->hashAlgorithm); if (!md) goto err; if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* * Could perform more salt length sanity checks but the main RSA * routines will trap other invalid values anyway. */ if (saltlen < 0) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_SALT_LENGTH); goto err; } } else saltlen = 20; /* * low-level routines support only trailer field 0xbc (value 1) and * PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_TRAILER); goto err; } /* We have all parameters now set up context */ if (pkey) { if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; } else { const EVP_MD *checkmd; if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) goto err; if (EVP_MD_type(md) != EVP_MD_type(checkmd)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH); goto err; } } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_PSS_PARAMS_free(pss); X509_ALGOR_free(maskHash); return rv; }
int main(int argc, char **argv) { EVP_PKEY *private_key, *public_key; EVP_PKEY_CTX *pkey_ctx; EVP_MD_CTX *md_ctx; const EVP_MD *digest_algo; char *private_key_name, *public_key_name; unsigned char sig[4096]; size_t sig_len; unsigned char md[128]; size_t md_len; unsigned digest_len; char *key_pass = NULL; const char *module_path, *efile; ENGINE *e; int ret; if (argc < 5) { fprintf(stderr, "usage: %s [PIN] [CONF] [private key URL] [public key URL] [module]\n", argv[0]); fprintf(stderr, "\n"); exit(1); } key_pass = argv[1]; efile = argv[2]; private_key_name = argv[3]; public_key_name = argv[4]; module_path = argv[5]; ret = CONF_modules_load_file(efile, "engines", 0); if (ret <= 0) { fprintf(stderr, "cannot load %s\n", efile); display_openssl_errors(__LINE__); exit(1); } ENGINE_add_conf_module(); #if OPENSSL_VERSION_NUMBER>=0x10100000 OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ | OPENSSL_INIT_ADD_ALL_DIGESTS \ | OPENSSL_INIT_LOAD_CONFIG, NULL); #else OpenSSL_add_all_algorithms(); OpenSSL_add_all_digests(); ERR_load_crypto_strings(); #endif ERR_clear_error(); ENGINE_load_builtin_engines(); e = ENGINE_by_id("pkcs11"); if (e == NULL) { display_openssl_errors(__LINE__); exit(1); } if (!ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0)) { display_openssl_errors(__LINE__); exit(1); } if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", module_path, 0)) { display_openssl_errors(__LINE__); exit(1); } if (!ENGINE_init(e)) { display_openssl_errors(__LINE__); exit(1); } if (key_pass && !ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) { display_openssl_errors(__LINE__); exit(1); } private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL); if (private_key == NULL) { fprintf(stderr, "cannot load: %s\n", private_key_name); display_openssl_errors(__LINE__); exit(1); } public_key = ENGINE_load_public_key(e, public_key_name, NULL, NULL); if (public_key == NULL) { fprintf(stderr, "cannot load: %s\n", public_key_name); display_openssl_errors(__LINE__); exit(1); } digest_algo = EVP_get_digestbyname("sha256"); #define TEST_DATA "test data" md_ctx = EVP_MD_CTX_create(); if (EVP_DigestInit(md_ctx, digest_algo) <= 0) { display_openssl_errors(__LINE__); exit(1); } if (EVP_DigestUpdate(md_ctx, TEST_DATA, sizeof(TEST_DATA)) <= 0) { display_openssl_errors(__LINE__); exit(1); } digest_len = sizeof(md); if (EVP_DigestFinal(md_ctx, md, &digest_len) <= 0) { display_openssl_errors(__LINE__); exit(1); } md_len = digest_len; EVP_MD_CTX_destroy(md_ctx); /* Sign the hash */ pkey_ctx = EVP_PKEY_CTX_new(private_key, e); if (pkey_ctx == NULL) { fprintf(stderr, "Could not create context\n"); display_openssl_errors(__LINE__); exit(1); } if (EVP_PKEY_sign_init(pkey_ctx) <= 0) { fprintf(stderr, "Could not init signature\n"); display_openssl_errors(__LINE__); exit(1); } if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "Could not set padding\n"); display_openssl_errors(__LINE__); exit(1); } if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, digest_algo) <= 0) { fprintf(stderr, "Could not set message digest algorithm\n"); display_openssl_errors(__LINE__); exit(1); } sig_len = sizeof(sig); if (EVP_PKEY_sign(pkey_ctx, sig, &sig_len, md, EVP_MD_size(digest_algo)) <= 0) { display_openssl_errors(__LINE__); exit(1); } EVP_PKEY_CTX_free(pkey_ctx); printf("Signature created\n"); #if OPENSSL_VERSION_NUMBER >= 0x1000000fL pkey_ctx = EVP_PKEY_CTX_new(public_key, e); if (pkey_ctx == NULL) { fprintf(stderr, "Could not create context\n"); display_openssl_errors(__LINE__); exit(1); } if (EVP_PKEY_verify_init(pkey_ctx) <= 0) { fprintf(stderr, "Could not init verify\n"); display_openssl_errors(__LINE__); exit(1); } if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "Could not set padding\n"); display_openssl_errors(__LINE__); exit(1); } if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, digest_algo) <= 0) { fprintf(stderr, "Could not set message digest algorithm\n"); display_openssl_errors(__LINE__); exit(1); } ret = EVP_PKEY_verify(pkey_ctx, sig, sig_len, md, md_len); if (ret < 0) { display_openssl_errors(__LINE__); exit(1); } EVP_PKEY_CTX_free(pkey_ctx); if (ret == 1) { printf("Signature verified\n"); } else { printf("Verification failed\n"); display_openssl_errors(__LINE__); exit(1); } #else /* OPENSSL_VERSION_NUMBER >= 0x1000000fL */ printf("Unable to verify signature with %s\n", OPENSSL_VERSION_TEXT); #endif /* OPENSSL_VERSION_NUMBER >= 0x1000000fL */ ENGINE_finish(e); CONF_modules_unload(1); return 0; }
/* From PSS AlgorithmIdentifier set public key parameters. */ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int ret = 0; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; EVP_PKEY_CTX *pkctx; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_UNSUPPORTED_SIGNATURE_TYPE); return 0; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_PSS_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); if (!mgf1md) { goto err; } md = rsa_algor_to_md(pss->hashAlgorithm); if (!md) { goto err; } saltlen = 20; if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_SALT_LENGTH); goto err; } } /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_TRAILER); goto err; } if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) { goto err; } ret = 1; err: RSA_PSS_PARAMS_free(pss); if (maskHash) { X509_ALGOR_free(maskHash); } return ret; }
static VALUE ORPV__verify_pss_sha1(VALUE self, VALUE vPubKey, VALUE vSig, VALUE vHashData, VALUE vSaltLen) { enum ORPV_errors err = OK; BIO * pkey_bio = NULL; RSA * rsa_pub_key = NULL; EVP_PKEY * pkey = NULL; EVP_PKEY_CTX * pkey_ctx = NULL; char * pub_key = NULL; int verify_rval = -1, salt_len; char ossl_err_strs[(OSSL_ERR_STR_LEN + 2) * ORPV_MAX_ERRS] = ""; if (ERR_peek_error()) { err = EXTERNAL; goto Cleanup; } vPubKey = StringValue(vPubKey); vSig = StringValue(vSig); vHashData = StringValue(vHashData); salt_len = NUM2INT(vSaltLen); if (RSTRING_LEN(vPubKey) > (long)INT_MAX) { err = KEY_OVERFLOW; goto Cleanup; } pub_key = malloc(RSTRING_LEN(vPubKey)); if (! pub_key) { err = NOMEM; goto Cleanup; } memcpy(pub_key, StringValuePtr(vPubKey), RSTRING_LEN(vPubKey)); pkey_bio = BIO_new_mem_buf(pub_key, (int)RSTRING_LEN(vPubKey)); rsa_pub_key = PEM_read_bio_RSA_PUBKEY(pkey_bio, NULL, NULL, NULL); if (! rsa_pub_key) { err = PUBKEY_PARSE; goto Cleanup; } pkey = EVP_PKEY_new(); if (! pkey) { err = PKEY_INIT; goto Cleanup; } if (! EVP_PKEY_set1_RSA(pkey, rsa_pub_key)) { err = RSA_ASSIGN; goto Cleanup; } pkey_ctx = EVP_PKEY_CTX_new(pkey, ENGINE_get_default_RSA()); if (! pkey_ctx) { err = PKEY_CTX_INIT; goto Cleanup; } if (EVP_PKEY_verify_init(pkey_ctx) <= 0) { err = VERIFY_INIT; goto Cleanup; } if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, EVP_sha1()) <= 0) { err = SET_SIG_MD; goto Cleanup; } if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) { err = SET_PADDING; goto Cleanup; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) <= 0) { err = SET_SALTLEN; goto Cleanup; } verify_rval = EVP_PKEY_verify(pkey_ctx, (unsigned char*)StringValuePtr(vSig), (size_t)RSTRING_LEN(vSig), (unsigned char*)StringValuePtr(vHashData), (size_t)RSTRING_LEN(vHashData)); Cleanup: /* * BIO * pkey_bio = NULL; * RSA * rsa_pub_key = NULL; * EVP_PKEY * pkey = NULL; * EVP_PKEY_CTX * pkey_ctx = NULL; * char * pub_key = NULL; */ if (pkey_ctx) EVP_PKEY_CTX_free(pkey_ctx); if (pkey) EVP_PKEY_free(pkey); if (rsa_pub_key) RSA_free(rsa_pub_key); if (pkey_bio) BIO_free(pkey_bio); if (pub_key) free(pub_key); switch (err) { case OK: switch (verify_rval) { case 1: return Qtrue; case 0: return Qfalse; default: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "An error occurred during validation.\n%s", ossl_err_strs); } break; case EXTERNAL: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_eRuntimeError, "OpenSSL was in an error state prior to invoking this verification.\n%s", ossl_err_strs); break; case KEY_OVERFLOW: rb_raise(rb_cRSAError, "Your public key is too big. How is that even possible?"); break; case NOMEM: rb_raise(rb_const_get_at(rb_mErrno, rb_intern("ENOMEM")), "Insufficient memory to allocate pubkey copy. Woof."); break; case PUBKEY_PARSE: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Error parsing public key\n%s", ossl_err_strs); break; case PKEY_INIT: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to initialize PKEY\n%s", ossl_err_strs); break; case RSA_ASSIGN: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to assign RSA object to PKEY\n%s", ossl_err_strs); break; case PKEY_CTX_INIT: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to initialize PKEY context.\n%s", ossl_err_strs); break; case VERIFY_INIT: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to initialize verification process.\n%s", ossl_err_strs); break; case SET_SIG_MD: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to set signature message digest to SHA1.\n%s", ossl_err_strs); break; case SET_PADDING: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to set PSS padding.\n%s", ossl_err_strs); break; case SET_SALTLEN: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to set salt length.\n%s", ossl_err_strs); break; default: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_eRuntimeError, "Something has gone horribly wrong.\n%s", ossl_err_strs); } return Qnil; }
static int rsa_cms_decrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pkctx; X509_ALGOR *cmsalg; int nid; int rv = -1; unsigned char *label = NULL; int labellen = 0; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_OAEP_PARAMS *oaep; X509_ALGOR *maskHash; pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pkctx) return 0; if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg)) return -1; nid = OBJ_obj2nid(cmsalg->algorithm); if (nid == NID_rsaEncryption) return 1; if (nid != NID_rsaesOaep) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE); return -1; } /* Decode OAEP parameters */ oaep = rsa_oaep_decode(cmsalg, &maskHash); if (oaep == NULL) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(oaep->maskGenFunc, maskHash); if (!mgf1md) goto err; md = rsa_algor_to_md(oaep->hashFunc); if (!md) goto err; if (oaep->pSourceFunc) { X509_ALGOR *plab = oaep->pSourceFunc; if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE); goto err; } if (plab->parameter->type != V_ASN1_OCTET_STRING) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL); goto err; } label = plab->parameter->value.octet_string->data; /* Stop label being freed when OAEP parameters are freed */ plab->parameter->value.octet_string->data = NULL; labellen = plab->parameter->value.octet_string->length; } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_OAEP_PARAMS_free(oaep); X509_ALGOR_free(maskHash); return rv; }
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (value == NULL) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); return 0; } if (strcmp(type, "rsa_padding_mode") == 0) { int pm; if (strcmp(value, "pkcs1") == 0) { pm = RSA_PKCS1_PADDING; } else if (strcmp(value, "sslv23") == 0) { pm = RSA_SSLV23_PADDING; } else if (strcmp(value, "none") == 0) { pm = RSA_NO_PADDING; } else if (strcmp(value, "oeap") == 0) { pm = RSA_PKCS1_OAEP_PADDING; } else if (strcmp(value, "oaep") == 0) { pm = RSA_PKCS1_OAEP_PADDING; } else if (strcmp(value, "x931") == 0) { pm = RSA_X931_PADDING; } else if (strcmp(value, "pss") == 0) { pm = RSA_PKCS1_PSS_PADDING; } else { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); return -2; } return EVP_PKEY_CTX_set_rsa_padding(ctx, pm); } if (strcmp(type, "rsa_pss_saltlen") == 0) { int saltlen; if (!strcmp(value, "digest")) saltlen = RSA_PSS_SALTLEN_DIGEST; else if (!strcmp(value, "max")) saltlen = RSA_PSS_SALTLEN_MAX; else if (!strcmp(value, "auto")) saltlen = RSA_PSS_SALTLEN_AUTO; else saltlen = atoi(value); return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); } if (strcmp(type, "rsa_keygen_bits") == 0) { int nbits; nbits = atoi(value); return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); } if (strcmp(type, "rsa_keygen_pubexp") == 0) { int ret; BIGNUM *pubexp = NULL; if (!BN_asc2bn(&pubexp, value)) return 0; ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp); if (ret <= 0) BN_free(pubexp); return ret; } if (strcmp(type, "rsa_mgf1_md") == 0) return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, EVP_PKEY_CTRL_RSA_MGF1_MD, value); if (pkey_ctx_is_pss(ctx)) { if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0) return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_MGF1_MD, value); if (strcmp(type, "rsa_pss_keygen_md") == 0) return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, value); if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) { int saltlen = atoi(value); return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen); } } if (strcmp(type, "rsa_oaep_md") == 0) return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT, EVP_PKEY_CTRL_RSA_OAEP_MD, value); if (strcmp(type, "rsa_oaep_label") == 0) { unsigned char *lab; long lablen; int ret; lab = OPENSSL_hexstr2buf(value, &lablen); if (!lab) return 0; ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen); if (ret <= 0) OPENSSL_free(lab); return ret; } return -2; }
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (!value) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); return 0; } if (!strcmp(type, "rsa_padding_mode")) { int pm; if (!strcmp(value, "pkcs1")) pm = RSA_PKCS1_PADDING; else if (!strcmp(value, "sslv23")) pm = RSA_SSLV23_PADDING; else if (!strcmp(value, "none")) pm = RSA_NO_PADDING; else if (!strcmp(value, "oeap")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "oaep")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "x931")) pm = RSA_X931_PADDING; else if (!strcmp(value, "pss")) pm = RSA_PKCS1_PSS_PADDING; else { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); return -2; } return EVP_PKEY_CTX_set_rsa_padding(ctx, pm); } if (!strcmp(type, "rsa_pss_saltlen")) { int saltlen; saltlen = atoi(value); return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); } if (!strcmp(type, "rsa_keygen_bits")) { int nbits; nbits = atoi(value); return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); } if (!strcmp(type, "rsa_keygen_pubexp")) { int ret; BIGNUM *pubexp = NULL; if (!BN_asc2bn(&pubexp, value)) return 0; ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp); if (ret <= 0) BN_free(pubexp); return ret; } if (!strcmp(type, "rsa_mgf1_md")) { const EVP_MD *md; if (!(md = EVP_get_digestbyname(value))) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md); } if (!strcmp(type, "rsa_oaep_md")) { const EVP_MD *md; if (!(md = EVP_get_digestbyname(value))) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md); } if (!strcmp(type, "rsa_oaep_label")) { unsigned char *lab; long lablen; int ret; lab = string_to_hex(value, &lablen); if (!lab) return 0; ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen); if (ret <= 0) OPENSSL_free(lab); return ret; } return -2; }
int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; int i = 0, ok = 0, v; EVP_MD_CTX tmp_ctx; EVP_PKEY_CTX *pkctx = NULL; *siglen = 0; EVP_MD_CTX_init(&tmp_ctx); if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) goto err; if (!EVP_DigestFinal_ex(&tmp_ctx, &(m[0]), &m_len)) goto err; EVP_MD_CTX_cleanup(&tmp_ctx); if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { size_t sltmp = (size_t)EVP_PKEY_size(pkey); i = 0; pkctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pkctx) goto err; if (EVP_PKEY_sign_init(pkctx) <= 0) goto err; if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) goto err; if (ctx->flags & EVP_MD_CTX_FLAG_PAD_X931) if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_X931_PADDING) <= 0) goto err; if (ctx->flags & EVP_MD_CTX_FLAG_PAD_PSS) { int saltlen; if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; saltlen = M_EVP_MD_CTX_FLAG_PSS_SALT(ctx); if (saltlen == EVP_MD_CTX_FLAG_PSS_MDLEN) saltlen = -1; else if (saltlen == EVP_MD_CTX_FLAG_PSS_MREC) saltlen = -2; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; } if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0) goto err; *siglen = sltmp; i = 1; err: EVP_PKEY_CTX_free(pkctx); return i; } for (i = 0; i < 4; i++) { v = ctx->digest->required_pkey_type[i]; if (v == 0) break; if (pkey->type == v) { ok = 1; break; } } if (!ok) { EVPerr(EVP_F_EVP_SIGNFINAL, EVP_R_WRONG_PUBLIC_KEY_TYPE); return (0); } if (ctx->digest->sign == NULL) { EVPerr(EVP_F_EVP_SIGNFINAL, EVP_R_NO_SIGN_FUNCTION_CONFIGURED); return (0); } return (ctx->digest->sign(ctx->digest->type, m, m_len, sigret, siglen, pkey->pkey.ptr)); }