static int sign_and_verify(int len) { /* * Per FIPS 186-4, the hash is recommended to be the same length as q. * If the hash is longer than q, the leftmost N bits are used; if the hash * is shorter, then we left-pad (see appendix C.2.1). */ size_t sigLength; int digestlen = BN_num_bytes(DSA_get0_q(dsakey)); int ok = 0; unsigned char *dataToSign = OPENSSL_malloc(len); unsigned char *paddedData = OPENSSL_malloc(digestlen); unsigned char *signature = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; if (!TEST_ptr(dataToSign) || !TEST_ptr(paddedData) || !TEST_int_eq(RAND_bytes(dataToSign, len), 1)) goto end; memset(paddedData, 0, digestlen); if (len > digestlen) memcpy(paddedData, dataToSign, digestlen); else memcpy(paddedData + digestlen - len, dataToSign, len); if (!TEST_ptr(pkey = EVP_PKEY_new())) goto end; EVP_PKEY_set1_DSA(pkey, dsakey); if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto end; if (!TEST_int_eq(EVP_PKEY_sign_init(ctx), 1)) goto end; if (EVP_PKEY_sign(ctx, NULL, &sigLength, dataToSign, len) != 1) { TEST_error("Failed to get signature length, len=%d", len); goto end; } if (!TEST_ptr(signature = OPENSSL_malloc(sigLength))) goto end; if (EVP_PKEY_sign(ctx, signature, &sigLength, dataToSign, len) != 1) { TEST_error("Failed to sign, len=%d", len); goto end; } /* Check that the signature is okay via the EVP interface */ if (!TEST_int_eq(EVP_PKEY_verify_init(ctx), 1)) goto end; /* ... using the same data we just signed */ if (EVP_PKEY_verify(ctx, signature, sigLength, dataToSign, len) != 1) { TEST_error("EVP verify with unpadded length %d failed\n", len); goto end; } /* ... padding/truncating the data to the appropriate digest size */ if (EVP_PKEY_verify(ctx, signature, sigLength, paddedData, digestlen) != 1) { TEST_error("EVP verify with length %d failed\n", len); goto end; } /* Verify again using the raw DSA interface */ if (DSA_verify(0, dataToSign, len, signature, sigLength, dsakey) != 1) { TEST_error("Verification with unpadded data failed, len=%d", len); goto end; } if (DSA_verify(0, paddedData, digestlen, signature, sigLength, dsakey) != 1) { TEST_error("verify with length %d failed\n", len); goto end; } ok = 1; end: EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); OPENSSL_free(signature); OPENSSL_free(paddedData); OPENSSL_free(dataToSign); return ok; }
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; }
static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri; CMS_EncryptedContentInfo *ec; EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; int ret = 0; if (ri->type != CMS_RECIPINFO_TRANS) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT); return 0; } ktri = ri->d.ktri; ec = cms->d.envelopedData->encryptedContentInfo; pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); if (!pctx) return 0; if (EVP_PKEY_encrypt_init(pctx) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR); goto err; } if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) goto err; ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); ek = NULL; ret = 1; err: if (pctx) EVP_PKEY_CTX_free(pctx); if (ek) OPENSSL_free(ek); return ret; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL, *impl = NULL; unsigned char *buf = NULL; int i, err = 1; const EVP_MD *md = NULL, *m; BIO *in = NULL, *inp; BIO *bmd = NULL; BIO *out = NULL; #define PROG_NAME_SIZE 39 char pname[PROG_NAME_SIZE + 1]; int separator = 0; int debug = 0; int keyform = FORMAT_PEM; const char *outfile = NULL, *keyfile = NULL; const char *sigfile = NULL, *randfile = NULL; int out_bin = -1, want_pub = 0, do_verify = 0; EVP_PKEY *sigkey = NULL; unsigned char *sigbuf = NULL; int siglen = 0; char *passargin = NULL, *passin = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; int engine_impl = 0; #endif char *hmac_key = NULL; char *mac_name = NULL; int non_fips_allow = 0; STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; apps_startup(); if ((buf = (unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL) { BIO_printf(bio_err, "out of memory\n"); goto end; } if (bio_err == NULL) if ((bio_err = BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; /* first check the program name */ program_name(argv[0], pname, sizeof pname); md = EVP_get_digestbyname(pname); argc--; argv++; while (argc > 0) { if ((*argv)[0] != '-') break; if (strcmp(*argv, "-c") == 0) separator = 1; else if (strcmp(*argv, "-r") == 0) separator = 2; else if (strcmp(*argv, "-rand") == 0) { if (--argc < 1) break; randfile = *(++argv); } else if (strcmp(*argv, "-out") == 0) { if (--argc < 1) break; outfile = *(++argv); } else if (strcmp(*argv, "-sign") == 0) { if (--argc < 1) break; keyfile = *(++argv); } else if (!strcmp(*argv, "-passin")) { if (--argc < 1) break; passargin = *++argv; } else if (strcmp(*argv, "-verify") == 0) { if (--argc < 1) break; keyfile = *(++argv); want_pub = 1; do_verify = 1; } else if (strcmp(*argv, "-prverify") == 0) { if (--argc < 1) break; keyfile = *(++argv); do_verify = 1; } else if (strcmp(*argv, "-signature") == 0) { if (--argc < 1) break; sigfile = *(++argv); } else if (strcmp(*argv, "-keyform") == 0) { if (--argc < 1) break; keyform = str2fmt(*(++argv)); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv, "-engine") == 0) { if (--argc < 1) break; engine = *(++argv); e = setup_engine(bio_err, engine, 0); } else if (strcmp(*argv, "-engine_impl") == 0) engine_impl = 1; #endif else if (strcmp(*argv, "-hex") == 0) out_bin = 0; else if (strcmp(*argv, "-binary") == 0) out_bin = 1; else if (strcmp(*argv, "-d") == 0) debug = 1; else if (!strcmp(*argv, "-fips-fingerprint")) hmac_key = "etaonrishdlcupfm"; else if (strcmp(*argv, "-non-fips-allow") == 0) non_fips_allow = 1; else if (!strcmp(*argv, "-hmac")) { if (--argc < 1) break; hmac_key = *++argv; } else if (!strcmp(*argv, "-mac")) { if (--argc < 1) break; mac_name = *++argv; } else if (strcmp(*argv, "-sigopt") == 0) { if (--argc < 1) break; if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) break; } else if (strcmp(*argv, "-macopt") == 0) { if (--argc < 1) break; if (!macopts) macopts = sk_OPENSSL_STRING_new_null(); if (!macopts || !sk_OPENSSL_STRING_push(macopts, *(++argv))) break; } else if ((m = EVP_get_digestbyname(&((*argv)[1]))) != NULL) md = m; else break; argc--; argv++; } if (keyfile != NULL && argc > 1) { BIO_printf(bio_err, "Can only sign or verify one file\n"); goto end; } if (do_verify && !sigfile) { BIO_printf(bio_err, "No signature to verify: use the -signature option\n"); goto end; } if ((argc > 0) && (argv[0][0] == '-')) { /* bad option */ BIO_printf(bio_err, "unknown option '%s'\n", *argv); BIO_printf(bio_err, "options are\n"); BIO_printf(bio_err, "-c to output the digest with separating colons\n"); BIO_printf(bio_err, "-r to output the digest in coreutils format\n"); BIO_printf(bio_err, "-d to output debug info\n"); BIO_printf(bio_err, "-hex output as hex dump\n"); BIO_printf(bio_err, "-binary output in binary form\n"); BIO_printf(bio_err, "-hmac arg set the HMAC key to arg\n"); BIO_printf(bio_err, "-non-fips-allow allow use of non FIPS digest\n"); BIO_printf(bio_err, "-sign file sign digest using private key in file\n"); BIO_printf(bio_err, "-verify file verify a signature using public key in file\n"); BIO_printf(bio_err, "-prverify file verify a signature using private key in file\n"); BIO_printf(bio_err, "-keyform arg key file format (PEM or ENGINE)\n"); BIO_printf(bio_err, "-out filename output to filename rather than stdout\n"); BIO_printf(bio_err, "-signature file signature to verify\n"); BIO_printf(bio_err, "-sigopt nm:v signature parameter\n"); BIO_printf(bio_err, "-hmac key create hashed MAC with key\n"); BIO_printf(bio_err, "-mac algorithm create MAC (not neccessarily HMAC)\n"); BIO_printf(bio_err, "-macopt nm:v MAC algorithm parameters or key\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); #endif EVP_MD_do_all_sorted(list_md_fn, bio_err); goto end; } #ifndef OPENSSL_NO_ENGINE if (engine_impl) impl = e; #endif in = BIO_new(BIO_s_file()); bmd = BIO_new(BIO_f_md()); if ((in == NULL) || (bmd == NULL)) { ERR_print_errors(bio_err); goto end; } if (debug) { BIO_set_callback(in, BIO_debug_callback); /* needed for windows 3.1 */ BIO_set_callback_arg(in, (char *)bio_err); } if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (out_bin == -1) { if (keyfile) out_bin = 1; else out_bin = 0; } if (randfile) app_RAND_load_file(randfile, bio_err, 0); if (outfile) { if (out_bin) out = BIO_new_file(outfile, "wb"); else out = BIO_new_file(outfile, "w"); } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } if (!out) { BIO_printf(bio_err, "Error opening output file %s\n", outfile ? outfile : "(stdout)"); ERR_print_errors(bio_err); goto end; } if ((! !mac_name + ! !keyfile + ! !hmac_key) > 1) { BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n"); goto end; } if (keyfile) { if (want_pub) sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, e, "key file"); else sigkey = load_key(bio_err, keyfile, keyform, 0, passin, e, "key file"); if (!sigkey) { /* * load_[pub]key() has already printed an appropriate message */ goto end; } } if (mac_name) { EVP_PKEY_CTX *mac_ctx = NULL; int r = 0; if (!init_gen_str(bio_err, &mac_ctx, mac_name, impl, 0)) goto mac_end; if (macopts) { char *macopt; for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) { macopt = sk_OPENSSL_STRING_value(macopts, i); if (pkey_ctrl_string(mac_ctx, macopt) <= 0) { BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt); ERR_print_errors(bio_err); goto mac_end; } } } if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) { BIO_puts(bio_err, "Error generating key\n"); ERR_print_errors(bio_err); goto mac_end; } r = 1; mac_end: if (mac_ctx) EVP_PKEY_CTX_free(mac_ctx); if (r == 0) goto end; } if (non_fips_allow) { EVP_MD_CTX *md_ctx; BIO_get_md_ctx(bmd, &md_ctx); EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); } if (hmac_key) { sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, impl, (unsigned char *)hmac_key, -1); if (!sigkey) goto end; } if (sigkey) { EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; int r; if (!BIO_get_md_ctx(bmd, &mctx)) { BIO_printf(bio_err, "Error getting context\n"); ERR_print_errors(bio_err); goto end; } if (do_verify) r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); else r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); if (!r) { BIO_printf(bio_err, "Error setting context\n"); ERR_print_errors(bio_err); goto end; } if (sigopts) { char *sigopt; for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { sigopt = sk_OPENSSL_STRING_value(sigopts, i); if (pkey_ctrl_string(pctx, sigopt) <= 0) { BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); ERR_print_errors(bio_err); goto end; } } } } /* we use md as a filter, reading from 'in' */ else { EVP_MD_CTX *mctx = NULL; if (!BIO_get_md_ctx(bmd, &mctx)) { BIO_printf(bio_err, "Error getting context\n"); ERR_print_errors(bio_err); goto end; } if (md == NULL) md = EVP_md5(); if (!EVP_DigestInit_ex(mctx, md, impl)) { BIO_printf(bio_err, "Error setting digest %s\n", pname); ERR_print_errors(bio_err); goto end; } } if (sigfile && sigkey) { BIO *sigbio; sigbio = BIO_new_file(sigfile, "rb"); siglen = EVP_PKEY_size(sigkey); sigbuf = OPENSSL_malloc(siglen); if (!sigbio) { BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } if (!sigbuf) { BIO_printf(bio_err, "Out of memory\n"); ERR_print_errors(bio_err); goto end; } siglen = BIO_read(sigbio, sigbuf, siglen); BIO_free(sigbio); if (siglen <= 0) { BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } } inp = BIO_push(bmd, in); if (md == NULL) { EVP_MD_CTX *tctx; BIO_get_md_ctx(bmd, &tctx); md = EVP_MD_CTX_md(tctx); } if (argc == 0) { BIO_set_fp(in, stdin, BIO_NOCLOSE); err = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, siglen, NULL, NULL, "stdin", bmd); } else { const char *md_name = NULL, *sig_name = NULL; if (!out_bin) { if (sigkey) { const EVP_PKEY_ASN1_METHOD *ameth; ameth = EVP_PKEY_get0_asn1(sigkey); if (ameth) EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &sig_name, ameth); } if (md) md_name = EVP_MD_name(md); } err = 0; for (i = 0; i < argc; i++) { int r; if (BIO_read_filename(in, argv[i]) <= 0) { perror(argv[i]); err++; continue; } else r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, siglen, sig_name, md_name, argv[i], bmd); if (r) err = r; (void)BIO_reset(bmd); } } end: if (buf != NULL) { OPENSSL_cleanse(buf, BUFSIZE); OPENSSL_free(buf); } if (in != NULL) BIO_free(in); if (passin) OPENSSL_free(passin); BIO_free_all(out); EVP_PKEY_free(sigkey); if (sigopts) sk_OPENSSL_STRING_free(sigopts); if (macopts) sk_OPENSSL_STRING_free(macopts); if (sigbuf) OPENSSL_free(sigbuf); if (bmd != NULL) BIO_free(bmd); apps_shutdown(); OPENSSL_EXIT(err); }
static EVP_PKEY_CTX *init_ctx(int *pkeysize, char *keyfile, int keyform, int key_type, char *passargin, int pkey_op, ENGINE *e) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; char *passin = NULL; int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(bio_err, keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; } *pkeysize = EVP_PKEY_size(pkey); if (!pkey) goto end; ctx = EVP_PKEY_CTX_new(pkey, e); EVP_PKEY_free(pkey); if (!ctx) goto end; switch (pkey_op) { case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign_init(ctx); break; case EVP_PKEY_OP_VERIFY: rv = EVP_PKEY_verify_init(ctx); break; case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover_init(ctx); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt_init(ctx); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; } if (rv <= 0) { EVP_PKEY_CTX_free(ctx); ctx = NULL; } end: if (passin) OPENSSL_free(passin); return ctx; }
U8_EXPORT ssize_t u8_cryptic (int do_encrypt,const char *cname, const unsigned char *key,int keylen, const unsigned char *iv,int ivlen, u8_block_reader reader,u8_block_writer writer, void *readstate,void *writestate, u8_context caller) { if (strncasecmp(cname,"rsa",3)==0) { ENGINE *eng=ENGINE_get_default_RSA(); EVP_PKEY _pkey, *pkey; EVP_PKEY_CTX *ctx; int pubkeyin=(strncasecmp(cname,"rsapub",6)==0); const unsigned char *scankey=key; struct U8_BYTEBUF bb; int retval=-1; if (pubkeyin) pkey=d2i_PUBKEY(NULL,&scankey,keylen); else pkey=d2i_PrivateKey((EVP_PKEY_RSA),NULL,&scankey,keylen); if (!(pkey)) ctx=NULL; else { #if (OPENSSL_VERSION_NUMBER>=0x1000204fL) ctx=EVP_PKEY_CTX_new(pkey,eng); #else ctx=EVP_PKEY_CTX_new(pkey,NULL); #endif } if (ctx) { memset(&bb,0,sizeof(bb)); bb.u8_direction=u8_output_buffer; bb.u8_buf=bb.u8_ptr=(u8_byte *)u8_malloc(1024); bb.u8_lim=(u8_byte *)(bb.u8_buf+1024); bb.u8_growbuf=1; fill_bytebuf(&bb,reader,readstate);} if (!(ctx)) {} else if ((pubkeyin)? ((do_encrypt)?((retval=EVP_PKEY_encrypt_init(ctx))<0): ((retval=EVP_PKEY_verify_recover_init(ctx))<0)): ((do_encrypt)?((retval=EVP_PKEY_sign_init(ctx))<0): ((retval=EVP_PKEY_decrypt_init(ctx))<0))) {} else { unsigned char *in=bb.u8_buf; size_t inlen=bb.u8_ptr-bb.u8_buf; unsigned char *out=NULL; size_t outlen; if (pubkeyin) { if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,NULL,&outlen,in,inlen); else retval=EVP_PKEY_verify_recover(ctx,NULL,&outlen,in,inlen);} else if (do_encrypt) retval=EVP_PKEY_sign(ctx,NULL,&outlen,in,inlen); else retval=EVP_PKEY_decrypt(ctx,NULL,&outlen,in,inlen); if (retval<0) {} else if ((out=u8_malloc(outlen))==NULL) {} else if (pubkeyin) { if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,out,&outlen,in,inlen); else retval=EVP_PKEY_verify_recover(ctx,out,&outlen,in,inlen);} else if (do_encrypt) retval=EVP_PKEY_sign(ctx,out,&outlen,in,inlen); else retval=EVP_PKEY_decrypt(ctx,out,&outlen,in,inlen); if (retval<0) {} else retval=writer(out,outlen,writestate); if (out) u8_free(out);} u8_free(bb.u8_buf); if (retval<0) { unsigned long err=ERR_get_error(); char buf[512]; buf[0]='\0'; ERR_error_string_n(err,buf,512); u8_seterr(u8_InternalCryptoError,OPENSSL_CRYPTIC,u8_fromlibc((char *)buf)); ERR_clear_error();} if (ctx) EVP_PKEY_CTX_free(ctx); if (pkey) EVP_PKEY_free(pkey); return retval;} else { EVP_CIPHER_CTX ctx; int inlen, outlen, retval=0; ssize_t totalout=0, totalin=0; unsigned char inbuf[1024], outbuf[1024+EVP_MAX_BLOCK_LENGTH]; const EVP_CIPHER *cipher=((cname)?(EVP_get_cipherbyname(cname)): (EVP_aes_128_cbc())); if (cipher) { int needkeylen=EVP_CIPHER_key_length(cipher); int needivlen=EVP_CIPHER_iv_length(cipher); int blocksize=EVP_CIPHER_block_size(cipher); if (blocksize>1024) blocksize=1024; u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, " %s cipher=%s, keylen=%d/%d, ivlen=%d/%d, blocksize=%d\n", ((do_encrypt)?("encrypt"):("decrypt")), cname,keylen,needkeylen,ivlen,needivlen,blocksize); if ((needivlen)&&(ivlen)&&(ivlen!=needivlen)) return u8_reterr(u8_BadCryptoIV, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname)); memset(&ctx,0,sizeof(ctx)); EVP_CIPHER_CTX_init(&ctx); retval=EVP_CipherInit(&ctx, cipher, NULL, NULL, do_encrypt); if (retval==0) return u8_reterr(u8_CipherInit_Failed, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_strdup(cname)); retval=EVP_CIPHER_CTX_set_key_length(&ctx,keylen); if (retval==0) return u8_reterr(u8_BadCryptoKey, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_mkstring("%d!=%d(%s)",keylen,needkeylen,cname)); if ((needivlen)&&(ivlen!=needivlen)) return u8_reterr(u8_BadCryptoIV, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname)); retval=EVP_CipherInit(&ctx, cipher, key, iv, do_encrypt); if (retval==0) return u8_reterr(u8_CipherInit_Failed, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_strdup(cname)); while (1) { inlen = reader(inbuf,blocksize,readstate); if (inlen <= 0) { u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, "Finished %s(%s) with %ld in, %ld out", ((do_encrypt)?("encrypt"):("decrypt")), cname,totalin,totalout); break;} else totalin=totalin+inlen; if (!(EVP_CipherUpdate(&ctx,outbuf,&outlen,inbuf,inlen))) { char *details=u8_malloc(256); unsigned long err=ERR_get_error(); ERR_error_string_n(err,details,256); EVP_CIPHER_CTX_cleanup(&ctx); return u8_reterr(u8_InternalCryptoError, ((caller)?(caller):((u8_context)"u8_cryptic")), details);} else { u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, "%s(%s) consumed %d/%ld bytes, emitted %d/%ld bytes" " in=<%v>\n out=<%v>", ((do_encrypt)?("encrypt"):("decrypt")),cname, inlen,totalin,outlen,totalout+outlen, inbuf,inlen,outbuf,outlen); writer(outbuf,outlen,writestate); totalout=totalout+outlen;}} if (!(EVP_CipherFinal(&ctx,outbuf,&outlen))) { char *details=u8_malloc(256); unsigned long err=ERR_get_error(); ERR_error_string_n(err,details,256); EVP_CIPHER_CTX_cleanup(&ctx); return u8_reterr(u8_InternalCryptoError, ((caller)?(caller):(OPENSSL_CRYPTIC)), details);} else { writer(outbuf,outlen,writestate); u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, "%s(%s) done after consuming %ld/%ld bytes, emitting %ld/%ld bytes" "\n final out=<%v>", ((do_encrypt)?("encrypt"):("decrypt")),cname, inlen,totalin,outlen,totalout+outlen, outbuf,outlen); EVP_CIPHER_CTX_cleanup(&ctx); totalout=totalout+outlen; return totalout;}} else { char *details=u8_malloc(256); unsigned long err=ERR_get_error(); ERR_error_string_n(err,details,256); return u8_reterr("Unknown cipher", ((caller)?(caller):((u8_context)"u8_cryptic")), details);} } }
// Key factory bool OSSLGOST::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) { // Check parameters if ((ppKeyPair == NULL) || (parameters == NULL)) { return false; } if (!parameters->areOfType(ECParameters::type)) { ERROR_MSG("Invalid parameters supplied for GOST key generation"); return false; } ECParameters* params = (ECParameters*) parameters; ByteString paramA = "06072a850302022301"; if (params->getEC() != paramA) { ERROR_MSG("unsupported parameters"); return false; } // Generate the key-pair EVP_PKEY_CTX* ctx = NULL; EVP_PKEY* pkey = NULL; OSSLGOSTKeyPair* kp; ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL); if (ctx == NULL) { ERROR_MSG("EVP_PKEY_CTX_new_id failed"); goto err; } if (EVP_PKEY_keygen_init(ctx) <= 0) { ERROR_MSG("EVP_PKEY_keygen_init failed"); goto err; } if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) { ERROR_MSG("EVP_PKEY_CTX_ctrl_str failed"); goto err; } if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { ERROR_MSG("EVP_PKEY_keygen failed"); goto err; } EVP_PKEY_CTX_free(ctx); ctx = NULL; // Create an asymmetric key-pair object to return kp = new OSSLGOSTKeyPair(); ((OSSLGOSTPublicKey*) kp->getPublicKey())->setFromOSSL(pkey); ((OSSLGOSTPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey); *ppKeyPair = kp; // Release the key EVP_PKEY_free(pkey); return true; err: if (ctx != NULL) EVP_PKEY_CTX_free(ctx); if (pkey != NULL) EVP_PKEY_free(pkey); return false; }
cjose_jwk_t *cjose_jwk_derive_ecdh_ephemeral_key( cjose_jwk_t *jwk_self, cjose_jwk_t *jwk_peer, cjose_err *err) { EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey_self = NULL; EVP_PKEY *pkey_peer = NULL; uint8_t *secret = NULL; size_t secret_len = 0; uint8_t *ephemeral_key = NULL; size_t ephemeral_key_len = 0; cjose_jwk_t *jwk_ephemeral_key = NULL; // get EVP_KEY from jwk_self if (!_cjose_jwk_evp_key_from_ec_key(jwk_self, &pkey_self, err)) { goto _cjose_jwk_derive_shared_secret_fail; } // get EVP_KEY from jwk_peer if (!_cjose_jwk_evp_key_from_ec_key(jwk_peer, &pkey_peer, err)) { goto _cjose_jwk_derive_shared_secret_fail; } // create derivation context based on local key pair ctx = EVP_PKEY_CTX_new(pkey_self, NULL); if (NULL == ctx) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // initialize derivation context if (1 != EVP_PKEY_derive_init(ctx)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // provide the peer public key if (1 != EVP_PKEY_derive_set_peer(ctx, pkey_peer)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // determine buffer length for shared secret if(1 != EVP_PKEY_derive(ctx, NULL, &secret_len)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // allocate buffer for shared secret secret = (uint8_t *)cjose_get_alloc()(secret_len); if (NULL == secret) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); goto _cjose_jwk_derive_shared_secret_fail; } memset(secret, 0, secret_len); // derive the shared secret if (1 != (EVP_PKEY_derive(ctx, secret, &secret_len))) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); goto _cjose_jwk_derive_shared_secret_fail; } // HKDF of the DH shared secret (SHA256, no salt, no info, 256 bit expand) ephemeral_key_len = 32; ephemeral_key = (uint8_t *)cjose_get_alloc()(ephemeral_key_len); if (!cjose_jwk_hkdf(EVP_sha256(), (uint8_t *)"", 0, (uint8_t *)"", 0, secret, secret_len, ephemeral_key, ephemeral_key_len, err)) { goto _cjose_jwk_derive_shared_secret_fail; } // create a JWK of the shared secret jwk_ephemeral_key = cjose_jwk_create_oct_spec( ephemeral_key, ephemeral_key_len, err); if (NULL == jwk_ephemeral_key) { goto _cjose_jwk_derive_shared_secret_fail; } // happy path EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey_self); EVP_PKEY_free(pkey_peer); cjose_get_dealloc()(secret); cjose_get_dealloc()(ephemeral_key); return jwk_ephemeral_key; // fail path _cjose_jwk_derive_shared_secret_fail: if (NULL != ctx) { EVP_PKEY_CTX_free(ctx); } if (NULL != pkey_self) { EVP_PKEY_free(pkey_self); } if (NULL != pkey_peer) { EVP_PKEY_free(pkey_peer); } if (NULL != jwk_ephemeral_key) { cjose_jwk_release(jwk_ephemeral_key); } cjose_get_dealloc()(secret); cjose_get_dealloc()(ephemeral_key); return NULL; }
static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) { EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; int ret = -1; pctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pctx) return -1; if (EVP_PKEY_decrypt_init(pctx) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); goto err; } if (EVP_PKEY_decrypt(pctx, NULL, &eklen, ri->enc_key->data, ri->enc_key->length) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_decrypt(pctx, ek, &eklen, ri->enc_key->data, ri->enc_key->length) <= 0) { ret = 0; PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); goto err; } ret = 1; if (*pek) { OPENSSL_cleanse(*pek, *peklen); OPENSSL_free(*pek); } *pek = ek; *peklen = eklen; err: if (pctx) EVP_PKEY_CTX_free(pctx); if (!ret && ek) OPENSSL_free(ek); return ret; }
int verify(const char* keypath, BIGNUM* nonce, const uint8_t* sig, size_t slen){ // Nonce uint8_t* N; size_t Nlen; // Context and key EVP_PKEY_CTX *verctx; FILE* vkeyfh; EVP_PKEY *vkey=NULL; // Return codes and errors int err_code, ret_val=1; unsigned long vererr; /* * Open the public key of the client for verification */ vkeyfh = fopen(keypath,"r"); if(!vkeyfh) { fprintf(stderr, "%s: Cannot open the key file\n", __func__); ret_val = 0; goto exit_verify; } vkey = PEM_read_PUBKEY(vkeyfh, &vkey, NULL, NULL); if(!vkey){ fprintf(stderr,"Cannot read verification key from file %s\n", keypath); ret_val = 0; fclose(vkeyfh); goto exit_verify; } verctx = EVP_PKEY_CTX_new(vkey, NULL); if (!verctx){ fprintf(stderr,"Cannot create a verify context\n"); ret_val = 0; fclose(vkeyfh); EVP_PKEY_free(vkey); goto exit_verify; } if (EVP_PKEY_verify_init(verctx) <= 0){ fprintf(stderr,"Cannot initialize a verify context\n"); ret_val = 0; goto cleanup_verify; } /* * Convert the nonce in a string so that it can be verified */ N = malloc(BN_num_bytes(nonce)); if (N == NULL) { fprintf(stderr, "%s: Out of memory\n", __func__); ret_val = 0; goto cleanup_verify; } Nlen = BN_bn2bin(nonce, N); /* Perform actual verify operation */ err_code = EVP_PKEY_verify(verctx, sig, slen, N, Nlen); if( err_code != 1 ){ ERR_load_crypto_strings(); vererr = ERR_get_error(); fprintf(stderr,"The verify operation on the nonce has failed with code %lu. RET=%d\n",vererr,err_code); fprintf(stderr,"%s\n", ERR_error_string(vererr, NULL)); ERR_free_strings(); ret_val = 0; } free(N); cleanup_verify: EVP_PKEY_CTX_free(verctx); EVP_PKEY_free(vkey); fclose(vkeyfh); exit_verify: return ret_val; }
static int test_kdf_scrypt(void) { int ret = 0; EVP_PKEY_CTX *pctx; unsigned char out[64]; size_t outlen = sizeof(out); if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL)) == NULL) { TEST_error("EVP_PKEY_SCRYPT"); goto err; } if (EVP_PKEY_derive_init(pctx) <= 0) { TEST_error("EVP_PKEY_derive_init"); goto err; } if (EVP_PKEY_CTX_set1_pbe_pass(pctx, "password", 8) <= 0) { TEST_error("EVP_PKEY_CTX_set1_pbe_pass"); goto err; } if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) { TEST_error("EVP_PKEY_CTX_set1_scrypt_salt"); goto err; } if (EVP_PKEY_CTX_set_scrypt_N(pctx, 1024) <= 0) { TEST_error("EVP_PKEY_CTX_set_scrypt_N"); goto err; } if (EVP_PKEY_CTX_set_scrypt_r(pctx, 8) <= 0) { TEST_error("EVP_PKEY_CTX_set_scrypt_r"); goto err; } if (EVP_PKEY_CTX_set_scrypt_p(pctx, 16) <= 0) { TEST_error("EVP_PKEY_CTX_set_scrypt_p"); goto err; } if (EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 16) <= 0) { TEST_error("EVP_PKEY_CTX_set_maxmem_bytes"); goto err; } if (EVP_PKEY_derive(pctx, out, &outlen) > 0) { TEST_error("EVP_PKEY_derive should have failed"); goto err; } if (EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 10 * 1024 * 1024) <= 0) { TEST_error("EVP_PKEY_CTX_set_maxmem_bytes"); goto err; } if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) { TEST_error("EVP_PKEY_derive"); goto err; } { const unsigned char expected[sizeof(out)] = { 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40 }; if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) { goto err; } } ret = 1; err: EVP_PKEY_CTX_free(pctx); return ret; }
uint8_t* sign(const char* keypath, const uint8_t* payload, const size_t plen, size_t* slen){ FILE* ckeyfh; EVP_PKEY* ckey=NULL; EVP_PKEY_CTX* sigctx; uint8_t *sig; // Load signing key ckeyfh = fopen(keypath,"r"); if(!ckeyfh) { fprintf(stderr, "%s: Cannot open the key file\n", __func__); sig = NULL; goto exit_sign; } ckey = PEM_read_PrivateKey(ckeyfh, &ckey, NULL, NULL); if(!ckey){ fprintf(stderr,"Cannot read signing key from file %s\n", keypath); fclose(ckeyfh); sig = NULL; goto exit_sign; } // create signing context sigctx = EVP_PKEY_CTX_new(ckey, NULL); if (!sigctx){ fprintf(stderr,"Cannot create a signing context\n"); fclose(ckeyfh); sig = NULL; EVP_PKEY_free(ckey); goto exit_sign; } if (EVP_PKEY_sign_init(sigctx) <= 0){ fprintf(stderr,"Cannot inizialize a signing context\n"); sig = NULL; goto cleanup_sign; } // Ask the maximum signature size that will result in signing the payload if (EVP_PKEY_sign(sigctx, NULL, slen, payload, plen ) <= 0) { fprintf(stderr, "%s: Cannot get signature size\n", __func__); sig = NULL; goto cleanup_sign; } sig = malloc(*slen); if(!sig){ fprintf(stderr,"Out of memory\n"); goto cleanup_sign; } // Do the real signature if (EVP_PKEY_sign(sigctx, sig, slen, payload, plen) <= 0){ ERR_load_crypto_strings(); fprintf(stderr,"Signing operation failed\n"); printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); ERR_free_strings(); sig = NULL; } cleanup_sign: fclose(ckeyfh); EVP_PKEY_CTX_free(sigctx); EVP_PKEY_free(ckey); exit_sign: return sig; }
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; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; char **args, *outfile = NULL; char *passarg = NULL; BIO *in = NULL, *out = NULL; const EVP_CIPHER *cipher = NULL; int outformat; int text = 0; EVP_PKEY *pkey=NULL; EVP_PKEY_CTX *ctx = NULL; char *pass = NULL; int badarg = 0; int ret = 1, rv; int do_param = 0; if (bio_err == NULL) bio_err = BIO_new_fp (OPENSSL_TYPE__FILE_STDERR, BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; outformat=FORMAT_PEM; ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); args = argv + 1; while (!badarg && *args && *args[0] == '-') { if (!TINYCLR_SSL_STRCMP(*args,"-outform")) { if (args[1]) { args++; outformat=str2fmt(*args); } else badarg = 1; } else if (!TINYCLR_SSL_STRCMP(*args,"-pass")) { if (!args[1]) goto bad; passarg= *(++args); } #ifndef OPENSSL_NO_ENGINE else if (TINYCLR_SSL_STRCMP(*args,"-engine") == 0) { if (!args[1]) goto bad; e = setup_engine(bio_err, *(++args), 0); } #endif else if (!TINYCLR_SSL_STRCMP (*args, "-paramfile")) { if (!args[1]) goto bad; args++; if (do_param == 1) goto bad; if (!init_keygen_file(bio_err, &ctx, *args, e)) goto end; } else if (!TINYCLR_SSL_STRCMP (*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; } else if (TINYCLR_SSL_STRCMP(*args,"-algorithm") == 0) { if (!args[1]) goto bad; if (!init_gen_str(bio_err, &ctx, *(++args),e, do_param)) goto end; } else if (TINYCLR_SSL_STRCMP(*args,"-pkeyopt") == 0) { if (!args[1]) goto bad; if (!ctx) { BIO_puts(bio_err, "No keytype specified\n"); goto bad; } else if (pkey_ctrl_string(ctx, *(++args)) <= 0) { BIO_puts(bio_err, "parameter setting error\n"); ERR_print_errors(bio_err); goto end; } } else if (TINYCLR_SSL_STRCMP(*args,"-genparam") == 0) { if (ctx) goto bad; do_param = 1; } else if (TINYCLR_SSL_STRCMP(*args,"-text") == 0) text=1; else { cipher = EVP_get_cipherbyname(*args + 1); if (!cipher) { BIO_printf(bio_err, "Unknown cipher %s\n", *args + 1); badarg = 1; } if (do_param == 1) badarg = 1; } args++; } if (!ctx) badarg = 1; if (badarg) { bad: BIO_printf(bio_err, "Usage: genpkey [options]\n"); BIO_printf(bio_err, "where options may be\n"); BIO_printf(bio_err, "-out file output file\n"); BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); BIO_printf(bio_err, "-pass arg output file pass phrase source\n"); BIO_printf(bio_err, "-<cipher> use cipher <cipher> to encrypt the key\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err, "-paramfile file parameters file\n"); BIO_printf(bio_err, "-algorithm alg the public key algorithm\n"); BIO_printf(bio_err, "-pkeyopt opt:value set the public key algorithm option <opt>\n" " to value <value>\n"); BIO_printf(bio_err, "-genparam generate parameters, not key\n"); BIO_printf(bio_err, "-text print the in text\n"); BIO_printf(bio_err, "NB: options order may be important! See the manual page.\n"); goto end; } if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_puts(bio_err, "Error getting password\n"); goto end; } if (outfile) { if (!(out = BIO_new_file (outfile, "wb"))) { BIO_printf(bio_err, "Can't open output file %s\n", outfile); goto end; } } else { out = BIO_new_fp (OPENSSL_TYPE__FILE_STDOUT, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); if (do_param) { if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { BIO_puts(bio_err, "Error generating parameters\n"); ERR_print_errors(bio_err); goto end; } } else { if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { BIO_puts(bio_err, "Error generating key\n"); ERR_print_errors(bio_err); goto end; } } if (do_param) rv = PEM_write_bio_Parameters(out, pkey); else if (outformat == FORMAT_PEM) rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass); else if (outformat == FORMAT_ASN1) rv = i2d_PrivateKey_bio(out, pkey); else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } if (rv <= 0) { BIO_puts(bio_err, "Error writing key\n"); ERR_print_errors(bio_err); } if (text) { if (do_param) rv = EVP_PKEY_print_params(out, pkey, 0, NULL); else rv = EVP_PKEY_print_private(out, pkey, 0, NULL); if (rv <= 0) { BIO_puts(bio_err, "Error printing key\n"); ERR_print_errors(bio_err); } } ret = 0; end: if (pkey) EVP_PKEY_free(pkey); if (ctx) EVP_PKEY_CTX_free(ctx); if (out) BIO_free_all(out); BIO_free(in); if (pass) OPENSSL_free(pass); return ret; }
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, char *passinarg, int pkey_op, ENGINE *e, const int engine_impl, EVP_PKEY **ppkey) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; ENGINE *impl = NULL; char *passin = NULL; int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(keyfile, keyform, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; case KEY_NONE: break; } #ifndef OPENSSL_NO_ENGINE if (engine_impl) impl = e; #endif if (kdfalg != NULL) { int kdfnid = OBJ_sn2nid(kdfalg); if (kdfnid == NID_undef) { kdfnid = OBJ_ln2nid(kdfalg); if (kdfnid == NID_undef) { BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n", kdfalg); goto end; } } ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); } else { EC_KEY *eckey = NULL; const EC_GROUP *group = NULL; int nid; if (pkey == NULL) goto end; /* SM2 needs a special treatment */ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (nid = EC_GROUP_get_curve_name(group)) == 0) goto end; if (nid == NID_sm2) EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); } *pkeysize = EVP_PKEY_size(pkey); ctx = EVP_PKEY_CTX_new(pkey, impl); if (ppkey != NULL) *ppkey = pkey; EVP_PKEY_free(pkey); } if (ctx == NULL) goto end; switch (pkey_op) { case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign_init(ctx); break; case EVP_PKEY_OP_VERIFY: rv = EVP_PKEY_verify_init(ctx); break; case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover_init(ctx); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt_init(ctx); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; } if (rv <= 0) { EVP_PKEY_CTX_free(ctx); ctx = NULL; } end: OPENSSL_free(passin); return ctx; }
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 = NULL; 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; }
int pkeyutl_main(int argc, char **argv) { BIO *in = NULL, *out = NULL; ENGINE *e = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; char hexdump = 0, asn1parse = 0, rev = 0, *prog; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; OPTION_CHOICE o; int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM; int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; int engine_impl = 0; int ret = 1, rv = -1; size_t buf_outlen; const char *inkey = NULL; const char *peerkey = NULL; const char *kdfalg = NULL; int kdflen = 0; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL; int rawin = 0; const EVP_MD *md = NULL; prog = opt_init(argc, argv, pkeyutl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(pkeyutl_options); ret = 0; goto end; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_SIGFILE: sigfile = opt_arg(); break; case OPT_ENGINE_IMPL: engine_impl = 1; break; case OPT_INKEY: inkey = opt_arg(); break; case OPT_PEERKEY: peerkey = opt_arg(); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_PEERFORM: if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform)) goto opthelp; break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform)) goto opthelp; break; case OPT_R_CASES: if (!opt_rand(o)) goto end; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_PUBIN: key_type = KEY_PUBKEY; break; case OPT_CERTIN: key_type = KEY_CERT; break; case OPT_ASN1PARSE: asn1parse = 1; break; case OPT_HEXDUMP: hexdump = 1; break; case OPT_SIGN: pkey_op = EVP_PKEY_OP_SIGN; break; case OPT_VERIFY: pkey_op = EVP_PKEY_OP_VERIFY; break; case OPT_VERIFYRECOVER: pkey_op = EVP_PKEY_OP_VERIFYRECOVER; break; case OPT_ENCRYPT: pkey_op = EVP_PKEY_OP_ENCRYPT; break; case OPT_DECRYPT: pkey_op = EVP_PKEY_OP_DECRYPT; break; case OPT_DERIVE: pkey_op = EVP_PKEY_OP_DERIVE; break; case OPT_KDF: pkey_op = EVP_PKEY_OP_DERIVE; key_type = KEY_NONE; kdfalg = opt_arg(); break; case OPT_KDFLEN: kdflen = atoi(opt_arg()); break; case OPT_REV: rev = 1; break; case OPT_PKEYOPT: if ((pkeyopts == NULL && (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) { BIO_puts(bio_err, "out of memory\n"); goto end; } break; case OPT_PKEYOPT_PASSIN: if ((pkeyopts_passin == NULL && (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) || sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) { BIO_puts(bio_err, "out of memory\n"); goto end; } break; case OPT_RAWIN: rawin = 1; break; case OPT_DIGEST: if (!opt_md(opt_arg(), &md)) goto end; break; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) { BIO_printf(bio_err, "%s: -rawin can only be used with -sign or -verify\n", prog); goto opthelp; } if (md != NULL && !rawin) { BIO_printf(bio_err, "%s: -digest can only be used with -rawin\n", prog); goto opthelp; } if (rawin && rev) { BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", prog); goto opthelp; } if (kdfalg != NULL) { if (kdflen == 0) { BIO_printf(bio_err, "%s: no KDF length given (-kdflen parameter).\n", prog); goto opthelp; } } else if (inkey == NULL) { BIO_printf(bio_err, "%s: no private key given (-inkey parameter).\n", prog); goto opthelp; } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) { BIO_printf(bio_err, "%s: no peer key given (-peerkey parameter).\n", prog); goto opthelp; } ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, passinarg, pkey_op, e, engine_impl, &pkey); if (ctx == NULL) { BIO_printf(bio_err, "%s: Error initializing context\n", prog); ERR_print_errors(bio_err); goto end; } if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) { BIO_printf(bio_err, "%s: Error setting up peer key\n", prog); ERR_print_errors(bio_err); goto end; } if (pkeyopts != NULL) { int num = sk_OPENSSL_STRING_num(pkeyopts); int i; for (i = 0; i < num; ++i) { const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i); if (pkey_ctrl_string(ctx, opt) <= 0) { BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n", prog, opt); ERR_print_errors(bio_err); goto end; } } } if (pkeyopts_passin != NULL) { int num = sk_OPENSSL_STRING_num(pkeyopts_passin); int i; for (i = 0; i < num; i++) { char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i); char *passin = strchr(opt, ':'); char *passwd; if (passin == NULL) { /* Get password interactively */ char passwd_buf[4096]; BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt); EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1, passwd_buf, 0); passwd = OPENSSL_strdup(passwd_buf); if (passwd == NULL) { BIO_puts(bio_err, "out of memory\n"); goto end; } } else { /* Get password as a passin argument: First split option name * and passphrase argument into two strings */ *passin = 0; passin++; if (app_passwd(passin, NULL, &passwd, NULL) == 0) { BIO_printf(bio_err, "failed to get '%s'\n", opt); goto end; } } if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) { BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n", prog, opt); goto end; } OPENSSL_free(passwd); } } if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) { BIO_printf(bio_err, "%s: Signature file specified for non verify\n", prog); goto end; } if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) { BIO_printf(bio_err, "%s: No signature file specified for verify\n", prog); goto end; } if (pkey_op != EVP_PKEY_OP_DERIVE) { in = bio_open_default(infile, 'r', FORMAT_BINARY); if (in == NULL) goto end; } out = bio_open_default(outfile, 'w', FORMAT_BINARY); if (out == NULL) goto end; if (sigfile != NULL) { BIO *sigbio = BIO_new_file(sigfile, "rb"); if (sigbio == NULL) { BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); goto end; } siglen = bio_to_mem(&sig, keysize * 10, sigbio); BIO_free(sigbio); if (siglen < 0) { BIO_printf(bio_err, "Error reading signature data\n"); goto end; } } /* Raw input data is handled elsewhere */ if (in != NULL && !rawin) { /* Read the input data */ buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); if (buf_inlen < 0) { BIO_printf(bio_err, "Error reading input Data\n"); goto end; } if (rev) { size_t i; unsigned char ctmp; size_t l = (size_t)buf_inlen; for (i = 0; i < l / 2; i++) { ctmp = buf_in[i]; buf_in[i] = buf_in[l - 1 - i]; buf_in[l - 1 - i] = ctmp; } } } /* Sanity check the input if the input is not raw */ if (!rawin && buf_inlen > EVP_MAX_MD_SIZE && (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY || pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) { BIO_printf(bio_err, "Error: The input data looks too long to be a hash\n"); goto end; } if (pkey_op == EVP_PKEY_OP_VERIFY) { if (rawin) { rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, sig, siglen, NULL, 0); } else { rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, buf_in, (size_t)buf_inlen); } if (rv == 1) { BIO_puts(out, "Signature Verified Successfully\n"); ret = 0; } else { BIO_puts(out, "Signature Verification Failure\n"); } goto end; } if (kdflen != 0) { buf_outlen = kdflen; rv = 1; } else { if (rawin) { /* rawin allocates the buffer in do_raw_keyop() */ rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, NULL, 0, &buf_out, (size_t *)&buf_outlen); } else { rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); if (rv > 0 && buf_outlen != 0) { buf_out = app_malloc(buf_outlen, "buffer output"); rv = do_keyop(ctx, pkey_op, buf_out, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); } } } if (rv <= 0) { if (pkey_op != EVP_PKEY_OP_DERIVE) { BIO_puts(bio_err, "Public Key operation error\n"); } else { BIO_puts(bio_err, "Key derivation failed\n"); } ERR_print_errors(bio_err); goto end; } ret = 0; if (asn1parse) { if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) ERR_print_errors(bio_err); } else if (hexdump) { BIO_dump(out, (char *)buf_out, buf_outlen); } else { BIO_write(out, buf_out, buf_outlen); } end: EVP_PKEY_CTX_free(ctx); release_engine(e); BIO_free(in); BIO_free_all(out); OPENSSL_free(buf_in); OPENSSL_free(buf_out); OPENSSL_free(sig); sk_OPENSSL_STRING_free(pkeyopts); sk_OPENSSL_STRING_free(pkeyopts_passin); return ret; }
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; }
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; }
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 (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)); }
// Signing functions bool OSSLGOST::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { if (mechanism == AsymMech::GOST) { // Separate implementation for GOST signing without hash computation // Check if the private key is the right type if (!privateKey->isOfType(OSSLGOSTPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } // In case of raw GOST, the length of the input data must be 32 bytes if (dataToSign.size() != 32) { ERROR_MSG("Size of data to sign is not 32 bytes"); return false; } // Perform the signature operation OSSLGOSTPrivateKey* osslKey = (OSSLGOSTPrivateKey*) privateKey; EVP_PKEY* pkey = osslKey->getOSSLKey(); size_t outLen; if (pkey == NULL) { ERROR_MSG("Could not get the OpenSSL private key"); return false; } signature.resize(EVP_PKEY_size(pkey)); outLen = signature.size(); EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey,NULL); if (ctx == NULL) { ERROR_MSG("EVP_PKEY_CTX_new failed"); return false; } if (EVP_PKEY_sign_init(ctx) <= 0) { ERROR_MSG("EVP_PKEY_sign_init failed"); EVP_PKEY_CTX_free(ctx); return false; } if (EVP_PKEY_sign(ctx, &signature[0], &outLen, dataToSign.const_byte_str(), dataToSign.size()) <= 0) { ERROR_MSG("An error occurred while performing a signature"); EVP_PKEY_CTX_free(ctx); return false; } signature.resize(outLen); EVP_PKEY_CTX_free(ctx); return true; } else { // Call default implementation return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); } }
bool bdoc::X509Cert::verifySignature(int digestMethod, int digestSize, std::vector<unsigned char> digest, std::vector<unsigned char> signature) { int result = 0; EVP_PKEY* key = getPublicKey(); switch (EVP_PKEY_type(key->type)) { case EVP_PKEY_RSA: { if (digest.size() > static_cast<size_t>(digestSize)) { // The digest already has an ASN.1 DigestInfo header. break; } X509_SIG *sig = X509_SIG_new(); // Prefer set0 to set_md, so we don't have to initialize the // digest lookup table with OpenSSL_add_all_digests. None of // our supported digests have parameters anyway. X509_ALGOR_set0(sig->algor, OBJ_nid2obj(digestMethod), V_ASN1_NULL, NULL); ASN1_OCTET_STRING_set(sig->digest, &digest[0], digest.size()); unsigned char *asn1 = NULL; size_t asn1_len = i2d_X509_SIG(sig, &asn1); digest = std::vector<unsigned char>(asn1, asn1 + asn1_len); X509_SIG_free(sig); break; } case EVP_PKEY_EC: { ECDSA_SIG *sig = ECDSA_SIG_new(); // signature is just r and s concatenated, so split them. size_t n_len = signature.size() >> 1; BN_bin2bn(&signature[0], n_len, sig->r); BN_bin2bn(&signature[n_len], n_len, sig->s); unsigned char *asn1 = NULL; size_t asn1_len = i2d_ECDSA_SIG(sig, &asn1); signature = std::vector<unsigned char>(asn1, asn1 + asn1_len); ECDSA_SIG_free(sig); break; } default: THROW_STACK_EXCEPTION("Certificate '%s' has an unsupported " "public key type, can not verify signature.", getSubject().c_str()); } EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); if (!ctx) { EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Creating signature verification " "context failed: %s", ERR_reason_error_string(ERR_get_error())); } if (EVP_PKEY_verify_init(ctx) <= 0) { EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Initializing signature " "verification context failed: %s", ERR_reason_error_string(ERR_get_error())); } result = EVP_PKEY_verify(ctx, &signature[0], signature.size(), &digest[0], digest.size()); if (result < 0) { EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Error during signature verification: %s", ERR_reason_error_string(ERR_get_error())); } EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return (result == 1); }
int pkeyutl_main(int argc, char **argv) { BIO *in = NULL, *out = NULL; ENGINE *e = NULL; EVP_PKEY_CTX *ctx = NULL; char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; char hexdump = 0, asn1parse = 0, rev = 0, *prog; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; OPTION_CHOICE o; int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM; int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; int ret = 1, rv = -1; size_t buf_outlen; prog = opt_init(argc, argv, pkeyutl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(pkeyutl_options); ret = 0; goto end; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_SIGFILE: sigfile = opt_arg(); break; case OPT_INKEY: ctx = init_ctx(&keysize, opt_arg(), keyform, key_type, passinarg, pkey_op, e); if (ctx == NULL) { BIO_puts(bio_err, "%s: Error initializing context\n"); ERR_print_errors(bio_err); goto opthelp; } break; case OPT_PEERKEY: if (!setup_peer(ctx, peerform, opt_arg())) goto opthelp; break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_PEERFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &peerform)) goto opthelp; break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyform)) goto opthelp; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_PUBIN: key_type = KEY_PUBKEY; break; case OPT_CERTIN: key_type = KEY_CERT; break; case OPT_ASN1PARSE: asn1parse = 1; break; case OPT_HEXDUMP: hexdump = 1; break; case OPT_SIGN: pkey_op = EVP_PKEY_OP_SIGN; break; case OPT_VERIFY: pkey_op = EVP_PKEY_OP_VERIFY; break; case OPT_VERIFYRECOVER: pkey_op = EVP_PKEY_OP_VERIFYRECOVER; break; case OPT_REV: rev = 1; case OPT_ENCRYPT: pkey_op = EVP_PKEY_OP_ENCRYPT; break; case OPT_DECRYPT: pkey_op = EVP_PKEY_OP_DECRYPT; break; case OPT_DERIVE: pkey_op = EVP_PKEY_OP_DERIVE; break; case OPT_PKEYOPT: if (ctx == NULL) { BIO_printf(bio_err, "%s: Must have -inkey before -pkeyopt\n", prog); goto opthelp; } if (pkey_ctrl_string(ctx, opt_arg()) <= 0) { BIO_printf(bio_err, "%s: Can't set parameter:\n", prog); ERR_print_errors(bio_err); goto end; } break; } } argc = opt_num_rest(); argv = opt_rest(); if (ctx == NULL) goto opthelp; if (!app_load_modules(NULL)) goto end; if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) { BIO_printf(bio_err, "%s: Signature file specified for non verify\n", prog); goto end; } if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) { BIO_printf(bio_err, "%s: No signature file specified for verify\n", prog); goto end; } /* FIXME: seed PRNG only if needed */ app_RAND_load_file(NULL, 0); if (pkey_op != EVP_PKEY_OP_DERIVE) { in = bio_open_default(infile, "rb"); if (in == NULL) goto end; } out = bio_open_default(outfile, "wb"); if (out == NULL) goto end; if (sigfile) { BIO *sigbio = BIO_new_file(sigfile, "rb"); if (!sigbio) { BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); goto end; } siglen = bio_to_mem(&sig, keysize * 10, sigbio); BIO_free(sigbio); if (siglen <= 0) { BIO_printf(bio_err, "Error reading signature data\n"); goto end; } } if (in) { /* Read the input data */ buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); if (buf_inlen <= 0) { BIO_printf(bio_err, "Error reading input Data\n"); exit(1); } if (rev) { size_t i; unsigned char ctmp; size_t l = (size_t)buf_inlen; for (i = 0; i < l / 2; i++) { ctmp = buf_in[i]; buf_in[i] = buf_in[l - 1 - i]; buf_in[l - 1 - i] = ctmp; } } } if (pkey_op == EVP_PKEY_OP_VERIFY) { rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, buf_in, (size_t)buf_inlen); if (rv == 1) { BIO_puts(out, "Signature Verified Successfully\n"); ret = 0; } else BIO_puts(out, "Signature Verification Failure\n"); goto end; } rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); if (rv > 0) { buf_out = app_malloc(buf_outlen, "buffer output"); rv = do_keyop(ctx, pkey_op, buf_out, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); } if (rv <= 0) { ERR_print_errors(bio_err); goto end; } ret = 0; if (asn1parse) { if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) ERR_print_errors(bio_err); } else if (hexdump) BIO_dump(out, (char *)buf_out, buf_outlen); else BIO_write(out, buf_out, buf_outlen); end: EVP_PKEY_CTX_free(ctx); BIO_free(in); BIO_free_all(out); OPENSSL_free(buf_in); OPENSSL_free(buf_out); OPENSSL_free(sig); return ret; }
int genpkey_main(int argc, char **argv) { char **args, *outfile = NULL; char *passarg = NULL; BIO *in = NULL, *out = NULL; const EVP_CIPHER *cipher = NULL; int outformat; int text = 0; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; char *pass = NULL; int badarg = 0; int ret = 1, rv; int do_param = 0; if (single_execution) { if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { perror("pledge"); exit(1); } } outformat = FORMAT_PEM; args = argv + 1; while (!badarg && *args && *args[0] == '-') { if (!strcmp(*args, "-outform")) { if (args[1]) { args++; outformat = str2fmt(*args); } else badarg = 1; } else if (!strcmp(*args, "-pass")) { if (!args[1]) goto bad; passarg = *(++args); } else if (!strcmp(*args, "-paramfile")) { if (!args[1]) goto bad; args++; if (do_param == 1) goto bad; if (!init_keygen_file(bio_err, &ctx, *args)) goto end; } else if (!strcmp(*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; } else if (strcmp(*args, "-algorithm") == 0) { if (!args[1]) goto bad; if (!init_gen_str(bio_err, &ctx, *(++args), do_param)) goto end; } else if (strcmp(*args, "-pkeyopt") == 0) { if (!args[1]) goto bad; if (!ctx) { BIO_puts(bio_err, "No keytype specified\n"); goto bad; } else if (pkey_ctrl_string(ctx, *(++args)) <= 0) { BIO_puts(bio_err, "parameter setting error\n"); ERR_print_errors(bio_err); goto end; } } else if (strcmp(*args, "-genparam") == 0) { if (ctx) goto bad; do_param = 1; } else if (strcmp(*args, "-text") == 0) text = 1; else { cipher = EVP_get_cipherbyname(*args + 1); if (!cipher) { BIO_printf(bio_err, "Unknown cipher %s\n", *args + 1); badarg = 1; } if (do_param == 1) badarg = 1; } args++; } if (!ctx) badarg = 1; if (badarg) { bad: BIO_printf(bio_err, "Usage: genpkey [options]\n"); BIO_printf(bio_err, "where options may be\n"); BIO_printf(bio_err, "-out file output file\n"); BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); BIO_printf(bio_err, "-pass arg output file pass phrase source\n"); BIO_printf(bio_err, "-<cipher> use cipher <cipher> to encrypt the key\n"); BIO_printf(bio_err, "-paramfile file parameters file\n"); BIO_printf(bio_err, "-algorithm alg the public key algorithm\n"); BIO_printf(bio_err, "-pkeyopt opt:value set the public key algorithm option <opt>\n" " to value <value>\n"); BIO_printf(bio_err, "-genparam generate parameters, not key\n"); BIO_printf(bio_err, "-text print the in text\n"); BIO_printf(bio_err, "NB: options order may be important! See the manual page.\n"); goto end; } if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_puts(bio_err, "Error getting password\n"); goto end; } if (outfile) { if (!(out = BIO_new_file(outfile, "wb"))) { BIO_printf(bio_err, "Can't open output file %s\n", outfile); goto end; } } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); } EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); if (do_param) { if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { BIO_puts(bio_err, "Error generating parameters\n"); ERR_print_errors(bio_err); goto end; } } else { if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { BIO_puts(bio_err, "Error generating key\n"); ERR_print_errors(bio_err); goto end; } } if (do_param) rv = PEM_write_bio_Parameters(out, pkey); else if (outformat == FORMAT_PEM) rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass); else if (outformat == FORMAT_ASN1) rv = i2d_PrivateKey_bio(out, pkey); else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } if (rv <= 0) { BIO_puts(bio_err, "Error writing key\n"); ERR_print_errors(bio_err); } if (text) { if (do_param) rv = EVP_PKEY_print_params(out, pkey, 0, NULL); else rv = EVP_PKEY_print_private(out, pkey, 0, NULL); if (rv <= 0) { BIO_puts(bio_err, "Error printing key\n"); ERR_print_errors(bio_err); } } ret = 0; end: if (pkey) EVP_PKEY_free(pkey); if (ctx) EVP_PKEY_CTX_free(ctx); if (out) BIO_free_all(out); BIO_free(in); free(pass); return ret; }
int MAIN(int argc, char **argv) { BIO *in = NULL, *out = NULL; char *infile = NULL, *outfile = NULL, *sigfile = NULL; ENGINE *e = NULL; int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; int keyform = FORMAT_PEM, peerform = FORMAT_PEM; char badarg = 0, rev = 0; char hexdump = 0, asn1parse = 0; EVP_PKEY_CTX *ctx = NULL; char *passargin = NULL; int keysize = -1; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; size_t buf_outlen; int buf_inlen = 0, siglen = -1; int ret = 1, rv = -1; argc--; argv++; if (!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); while (argc >= 1) { if (!strcmp(*argv, "-in")) { if (--argc < 1) badarg = 1; else infile = *(++argv); } else if (!strcmp(*argv, "-out")) { if (--argc < 1) badarg = 1; else outfile = *(++argv); } else if (!strcmp(*argv, "-sigfile")) { if (--argc < 1) badarg = 1; else sigfile = *(++argv); } else if (!strcmp(*argv, "-inkey")) { if (--argc < 1) badarg = 1; else { ctx = init_ctx(&keysize, *(++argv), keyform, key_type, passargin, pkey_op, e); if (!ctx) { BIO_puts(bio_err, "Error initializing context\n"); ERR_print_errors(bio_err); badarg = 1; } } } else if (!strcmp(*argv, "-peerkey")) { if (--argc < 1) badarg = 1; else if (!setup_peer(bio_err, ctx, peerform, *(++argv))) badarg = 1; } else if (!strcmp(*argv, "-passin")) { if (--argc < 1) badarg = 1; else passargin = *(++argv); } else if (strcmp(*argv, "-peerform") == 0) { if (--argc < 1) badarg = 1; else peerform = str2fmt(*(++argv)); } else if (strcmp(*argv, "-keyform") == 0) { if (--argc < 1) badarg = 1; else keyform = str2fmt(*(++argv)); } #ifndef OPENSSL_NO_ENGINE else if (!strcmp(*argv, "-engine")) { if (--argc < 1) badarg = 1; else e = setup_engine(bio_err, *(++argv), 0); } #endif else if (!strcmp(*argv, "-pubin")) key_type = KEY_PUBKEY; else if (!strcmp(*argv, "-certin")) key_type = KEY_CERT; else if (!strcmp(*argv, "-asn1parse")) asn1parse = 1; else if (!strcmp(*argv, "-hexdump")) hexdump = 1; else if (!strcmp(*argv, "-sign")) pkey_op = EVP_PKEY_OP_SIGN; else if (!strcmp(*argv, "-verify")) pkey_op = EVP_PKEY_OP_VERIFY; else if (!strcmp(*argv, "-verifyrecover")) pkey_op = EVP_PKEY_OP_VERIFYRECOVER; else if (!strcmp(*argv, "-rev")) rev = 1; else if (!strcmp(*argv, "-encrypt")) pkey_op = EVP_PKEY_OP_ENCRYPT; else if (!strcmp(*argv, "-decrypt")) pkey_op = EVP_PKEY_OP_DECRYPT; else if (!strcmp(*argv, "-derive")) pkey_op = EVP_PKEY_OP_DERIVE; else if (strcmp(*argv, "-pkeyopt") == 0) { if (--argc < 1) badarg = 1; else if (!ctx) { BIO_puts(bio_err, "-pkeyopt command before -inkey\n"); badarg = 1; } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) { BIO_puts(bio_err, "parameter setting error\n"); ERR_print_errors(bio_err); goto end; } } else badarg = 1; if (badarg) { usage(); goto end; } argc--; argv++; } if (!ctx) { usage(); goto end; } if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) { BIO_puts(bio_err, "Signature file specified for non verify\n"); goto end; } if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) { BIO_puts(bio_err, "No signature file specified for verify\n"); goto end; } /* FIXME: seed PRNG only if needed */ app_RAND_load_file(NULL, bio_err, 0); if (pkey_op != EVP_PKEY_OP_DERIVE) { if (infile) { if (!(in = BIO_new_file(infile, "rb"))) { BIO_puts(bio_err, "Error Opening Input File\n"); ERR_print_errors(bio_err); goto end; } } else in = BIO_new_fp(stdin, BIO_NOCLOSE); } if (outfile) { if (!(out = BIO_new_file(outfile, "wb"))) { BIO_printf(bio_err, "Error Creating Output File\n"); ERR_print_errors(bio_err); goto end; } } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } if (sigfile) { BIO *sigbio = BIO_new_file(sigfile, "rb"); if (!sigbio) { BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); goto end; } siglen = bio_to_mem(&sig, keysize * 10, sigbio); BIO_free(sigbio); if (siglen <= 0) { BIO_printf(bio_err, "Error reading signature data\n"); goto end; } } if (in) { /* Read the input data */ buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); if (buf_inlen <= 0) { BIO_printf(bio_err, "Error reading input Data\n"); exit(1); } if (rev) { size_t i; unsigned char ctmp; size_t l = (size_t)buf_inlen; for (i = 0; i < l / 2; i++) { ctmp = buf_in[i]; buf_in[i] = buf_in[l - 1 - i]; buf_in[l - 1 - i] = ctmp; } } } if (pkey_op == EVP_PKEY_OP_VERIFY) { rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, buf_in, (size_t)buf_inlen); if (rv == 0) BIO_puts(out, "Signature Verification Failure\n"); else if (rv == 1) BIO_puts(out, "Signature Verified Successfully\n"); if (rv >= 0) goto end; } else { rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); if (rv > 0) { buf_out = OPENSSL_malloc(buf_outlen); if (!buf_out) rv = -1; else rv = do_keyop(ctx, pkey_op, buf_out, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); } } if (rv <= 0) { BIO_printf(bio_err, "Public Key operation error\n"); ERR_print_errors(bio_err); goto end; } ret = 0; if (asn1parse) { if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) ERR_print_errors(bio_err); } else if (hexdump) BIO_dump(out, (char *)buf_out, buf_outlen); else BIO_write(out, buf_out, buf_outlen); end: if (ctx) EVP_PKEY_CTX_free(ctx); BIO_free(in); BIO_free_all(out); if (buf_in) OPENSSL_free(buf_in); if (buf_out) OPENSSL_free(buf_out); if (sig) OPENSSL_free(sig); return ret; }
/* 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; }
static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) { EVP_PKEY_CTX *ret; const EVP_PKEY_METHOD *pmeth; if (id == -1) { if (!pkey || !pkey->ameth) return NULL; id = pkey->ameth->pkey_id; } #ifndef OPENSSL_NO_ENGINE if (pkey && pkey->engine) e = pkey->engine; /* Try to find an ENGINE which implements this method */ if (e) { if (!ENGINE_init(e)) { EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB); return NULL; } } else e = ENGINE_get_pkey_meth_engine(id); /* * If an ENGINE handled this method look it up. Otherwise use internal * tables. */ if (e) pmeth = ENGINE_get_pkey_meth(e, id); else #endif pmeth = EVP_PKEY_meth_find(id); if (pmeth == NULL) { EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM); return NULL; } ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { #ifndef OPENSSL_NO_ENGINE ENGINE_finish(e); #endif EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE); return NULL; } ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; ret->pkey = pkey; if (pkey) EVP_PKEY_up_ref(pkey); if (pmeth->init) { if (pmeth->init(ret) <= 0) { EVP_PKEY_CTX_free(ret); return NULL; } } return ret; }
int dgst_main(int argc, char **argv) { BIO *in = NULL, *inp, *bmd = NULL, *out = NULL; ENGINE *e = NULL, *impl = NULL; EVP_PKEY *sigkey = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; char *hmac_key = NULL; char *mac_name = NULL; char *passinarg = NULL, *passin = NULL; const EVP_MD *md = NULL, *m; const char *outfile = NULL, *keyfile = NULL, *prog = NULL; const char *sigfile = NULL, *randfile = NULL; OPTION_CHOICE o; int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0; int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0; unsigned char *buf = NULL, *sigbuf = NULL; int engine_impl = 0; prog = opt_progname(argv[0]); buf = app_malloc(BUFSIZE, "I/O buffer"); md = EVP_get_digestbyname(prog); prog = opt_init(argc, argv, dgst_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(dgst_options); ret = 0; goto end; case OPT_C: separator = 1; break; case OPT_R: separator = 2; break; case OPT_RAND: randfile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_SIGN: keyfile = opt_arg(); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_VERIFY: keyfile = opt_arg(); want_pub = do_verify = 1; break; case OPT_PRVERIFY: keyfile = opt_arg(); do_verify = 1; break; case OPT_SIGNATURE: sigfile = opt_arg(); break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) goto opthelp; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_ENGINE_IMPL: engine_impl = 1; break; case OPT_HEX: out_bin = 0; break; case OPT_BINARY: out_bin = 1; break; case OPT_DEBUG: debug = 1; break; case OPT_FIPS_FINGERPRINT: hmac_key = "etaonrishdlcupfm"; break; case OPT_HMAC: hmac_key = opt_arg(); break; case OPT_MAC: mac_name = opt_arg(); break; case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; case OPT_MACOPT: if (!macopts) macopts = sk_OPENSSL_STRING_new_null(); if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg())) goto opthelp; break; case OPT_DIGEST: if (!opt_md(opt_unknown(), &m)) goto opthelp; md = m; break; } } argc = opt_num_rest(); argv = opt_rest(); if (keyfile != NULL && argc > 1) { BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog); goto end; } if (do_verify && !sigfile) { BIO_printf(bio_err, "No signature to verify: use the -signature option\n"); goto end; } if (engine_impl) impl = e; in = BIO_new(BIO_s_file()); bmd = BIO_new(BIO_f_md()); if ((in == NULL) || (bmd == NULL)) { ERR_print_errors(bio_err); goto end; } if (debug) { BIO_set_callback(in, BIO_debug_callback); /* needed for windows 3.1 */ BIO_set_callback_arg(in, (char *)bio_err); } if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (out_bin == -1) { if (keyfile) out_bin = 1; else out_bin = 0; } if (randfile) app_RAND_load_file(randfile, 0); out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); if (out == NULL) goto end; if ((! !mac_name + ! !keyfile + ! !hmac_key) > 1) { BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n"); goto end; } if (keyfile) { if (want_pub) sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file"); else sigkey = load_key(keyfile, keyform, 0, passin, e, "key file"); if (!sigkey) { /* * load_[pub]key() has already printed an appropriate message */ goto end; } } if (mac_name) { EVP_PKEY_CTX *mac_ctx = NULL; int r = 0; if (!init_gen_str(&mac_ctx, mac_name, impl, 0)) goto mac_end; if (macopts) { char *macopt; for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) { macopt = sk_OPENSSL_STRING_value(macopts, i); if (pkey_ctrl_string(mac_ctx, macopt) <= 0) { BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt); ERR_print_errors(bio_err); goto mac_end; } } } if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) { BIO_puts(bio_err, "Error generating key\n"); ERR_print_errors(bio_err); goto mac_end; } r = 1; mac_end: EVP_PKEY_CTX_free(mac_ctx); if (r == 0) goto end; } if (hmac_key) { sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, impl, (unsigned char *)hmac_key, -1); if (!sigkey) goto end; } if (sigkey) { EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; int r; if (!BIO_get_md_ctx(bmd, &mctx)) { BIO_printf(bio_err, "Error getting context\n"); ERR_print_errors(bio_err); goto end; } if (do_verify) r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); else r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); if (!r) { BIO_printf(bio_err, "Error setting context\n"); ERR_print_errors(bio_err); goto end; } if (sigopts) { char *sigopt; for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { sigopt = sk_OPENSSL_STRING_value(sigopts, i); if (pkey_ctrl_string(pctx, sigopt) <= 0) { BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); ERR_print_errors(bio_err); goto end; } } } } /* we use md as a filter, reading from 'in' */ else { EVP_MD_CTX *mctx = NULL; if (!BIO_get_md_ctx(bmd, &mctx)) { BIO_printf(bio_err, "Error getting context\n"); ERR_print_errors(bio_err); goto end; } if (md == NULL) md = EVP_sha256(); if (!EVP_DigestInit_ex(mctx, md, impl)) { BIO_printf(bio_err, "Error setting digest\n"); ERR_print_errors(bio_err); goto end; } } if (sigfile && sigkey) { BIO *sigbio = BIO_new_file(sigfile, "rb"); if (!sigbio) { BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } siglen = EVP_PKEY_size(sigkey); sigbuf = app_malloc(siglen, "signature buffer"); siglen = BIO_read(sigbio, sigbuf, siglen); BIO_free(sigbio); if (siglen <= 0) { BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } } inp = BIO_push(bmd, in); if (md == NULL) { EVP_MD_CTX *tctx; BIO_get_md_ctx(bmd, &tctx); md = EVP_MD_CTX_md(tctx); } if (argc == 0) { BIO_set_fp(in, stdin, BIO_NOCLOSE); ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, siglen, NULL, NULL, "stdin"); } else { const char *md_name = NULL, *sig_name = NULL; if (!out_bin) { if (sigkey) { const EVP_PKEY_ASN1_METHOD *ameth; ameth = EVP_PKEY_get0_asn1(sigkey); if (ameth) EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &sig_name, ameth); } if (md) md_name = EVP_MD_name(md); } ret = 0; for (i = 0; i < argc; i++) { int r; if (BIO_read_filename(in, argv[i]) <= 0) { perror(argv[i]); ret++; continue; } else r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, siglen, sig_name, md_name, argv[i]); if (r) ret = r; (void)BIO_reset(bmd); } } end: OPENSSL_clear_free(buf, BUFSIZE); BIO_free(in); OPENSSL_free(passin); BIO_free_all(out); EVP_PKEY_free(sigkey); sk_OPENSSL_STRING_free(sigopts); sk_OPENSSL_STRING_free(macopts); OPENSSL_free(sigbuf); BIO_free(bmd); release_engine(e); return (ret); }
static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; int ret = 0; CMS_EncryptedContentInfo *ec; ec = cms->d.envelopedData->encryptedContentInfo; if (ktri->pkey == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY); return 0; } pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); if (!pctx) return 0; if (EVP_PKEY_decrypt_init(pctx) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); goto err; } if (EVP_PKEY_decrypt(pctx, NULL, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_decrypt(pctx, ek, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); goto err; } ret = 1; if (ec->key) { OPENSSL_cleanse(ec->key, ec->keylen); OPENSSL_free(ec->key); } ec->key = ek; ec->keylen = eklen; err: if (pctx) EVP_PKEY_CTX_free(pctx); if (!ret && ek) OPENSSL_free(ek); return ret; }
ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */ DH *dh_params = NULL; int mpint; /* 0 or 4 */ { ERL_NIF_TERM head, tail; BIGNUM *dh_p = NULL, *dh_g = NULL, *priv_key_in = NULL; unsigned long len = 0; if (!(get_bn_from_bin(env, argv[0], &priv_key_in) || argv[0] == atom_undefined) || !enif_get_list_cell(env, argv[1], &head, &tail) || !get_bn_from_bin(env, head, &dh_p) || !enif_get_list_cell(env, tail, &head, &tail) || !get_bn_from_bin(env, head, &dh_g) || !enif_is_empty_list(env, tail) || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4) || !enif_get_ulong(env, argv[3], &len) /* Load dh_params with values to use by the generator. Mem mgmnt transfered from dh_p etc to dh_params */ || !(dh_params = DH_new()) || (priv_key_in && !DH_set0_key(dh_params, NULL, priv_key_in)) || !DH_set0_pqg(dh_params, dh_p, NULL, dh_g) ) { if (priv_key_in) BN_free(priv_key_in); if (dh_p) BN_free(dh_p); if (dh_g) BN_free(dh_g); if (dh_params) DH_free(dh_params); return enif_make_badarg(env); } if (len) { if (len < BN_num_bits(dh_p)) DH_set_length(dh_params, len); else { if (priv_key_in) BN_free(priv_key_in); if (dh_p) BN_free(dh_p); if (dh_g) BN_free(dh_g); if (dh_params) DH_free(dh_params); return enif_make_badarg(env); } } } #ifdef HAS_EVP_PKEY_CTX { EVP_PKEY_CTX *ctx; EVP_PKEY *dhkey, *params; int success; params = EVP_PKEY_new(); success = EVP_PKEY_set1_DH(params, dh_params); /* set the key referenced by params to dh_params... */ DH_free(dh_params); /* ...dh_params (and params) must be freed */ if (!success) return atom_error; ctx = EVP_PKEY_CTX_new(params, NULL); EVP_PKEY_free(params); if (!ctx) { return atom_error; } if (!EVP_PKEY_keygen_init(ctx)) { /* EVP_PKEY_CTX_free(ctx); */ return atom_error; } dhkey = EVP_PKEY_new(); if (!EVP_PKEY_keygen(ctx, &dhkey)) { /* "performs a key generation operation, the ... */ /*... generated key is written to ppkey." (=last arg) */ /* EVP_PKEY_CTX_free(ctx); */ /* EVP_PKEY_free(dhkey); */ return atom_error; } dh_params = EVP_PKEY_get1_DH(dhkey); /* return the referenced key. dh_params and dhkey must be freed */ EVP_PKEY_free(dhkey); if (!dh_params) { /* EVP_PKEY_CTX_free(ctx); */ return atom_error; } EVP_PKEY_CTX_free(ctx); } #else if (!DH_generate_key(dh_params)) return atom_error; #endif { unsigned char *pub_ptr, *prv_ptr; int pub_len, prv_len; ERL_NIF_TERM ret_pub, ret_prv; const BIGNUM *pub_key_gen, *priv_key_gen; DH_get0_key(dh_params, &pub_key_gen, &priv_key_gen); /* Get pub_key_gen and priv_key_gen. "The values point to the internal representation of the public key and private key values. This memory should not be freed directly." says man */ pub_len = BN_num_bytes(pub_key_gen); prv_len = BN_num_bytes(priv_key_gen); pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub); prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv); if (mpint) { put_int32(pub_ptr, pub_len); pub_ptr += 4; put_int32(prv_ptr, prv_len); prv_ptr += 4; } BN_bn2bin(pub_key_gen, pub_ptr); BN_bn2bin(priv_key_gen, prv_ptr); ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len); ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len); DH_free(dh_params); return enif_make_tuple2(env, ret_pub, ret_prv); } }