void do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, EVP_PKEY *key, unsigned char *sigin, int siglen) { int len; int i; for (;;) { i=BIO_read(bp,(char *)buf,BUFSIZE); if (i <= 0) break; } if(sigin) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key); if(i > 0) BIO_printf(out, "Verified OK\n"); else if(i == 0) BIO_printf(out, "Verification Failure\n"); else { BIO_printf(bio_err, "Error Verifying Data\n"); ERR_print_errors(bio_err); } return; } if(key) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key)) { BIO_printf(bio_err, "Error Signing Data\n"); ERR_print_errors(bio_err); return; } } else len=BIO_gets(bp,(char *)buf,BUFSIZE); if(binout) BIO_write(out, buf, len); else { for (i=0; i<len; i++) { if (sep && (i != 0)) BIO_printf(out, ":"); BIO_printf(out, "%02x",buf[i]); } BIO_printf(out, "\n"); } }
int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg) { int nid; ASN1_OBJECT *mdoid; X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); nid = OBJ_obj2nid(mdoid); /* Look for digest type to match signature */ for (;;) { EVP_MD_CTX *mtmp; chain = BIO_find_type(chain, BIO_TYPE_MD); if (chain == NULL) { CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, CMS_R_NO_MATCHING_DIGEST); return 0; } BIO_get_md_ctx(chain, &mtmp); if (EVP_MD_CTX_type(mtmp) == nid /* * Workaround for broken implementations that use signature * algorithm OID instead of digest. */ || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) return EVP_MD_CTX_copy_ex(mctx, mtmp); chain = BIO_next(chain); } }
static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) { for (;;) { bio = BIO_find_type(bio, BIO_TYPE_MD); if (bio == NULL) { PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); return NULL; } BIO_get_md_ctx(bio, pmd); if (*pmd == NULL) { PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); return NULL; } if (EVP_MD_CTX_type(*pmd) == nid) return bio; bio = BIO_next(bio); } return NULL; }
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, const char *file, BIO *bmd) { size_t len; int i; for (;;) { i = BIO_read(bp, (char *)buf, BUFSIZE); if (i < 0) { BIO_printf(bio_err, "Read Error in %s\n", file); ERR_print_errors(bio_err); return 1; } if (i == 0) break; } if (sigin) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen); if (i > 0) BIO_printf(out, "Verified OK\n"); else if (i == 0) { BIO_printf(out, "Verification Failure\n"); return 1; } else { BIO_printf(bio_err, "Error Verifying Data\n"); ERR_print_errors(bio_err); return 1; } return 0; } if (key) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); len = BUFSIZE; if (!EVP_DigestSignFinal(ctx, buf, &len)) { BIO_printf(bio_err, "Error Signing Data\n"); ERR_print_errors(bio_err); return 1; } } else { len = BIO_gets(bp, (char *)buf, BUFSIZE); if ((int)len < 0) { ERR_print_errors(bio_err); return 1; } } if (binout) BIO_write(out, buf, len); else if (sep == 2) { for (i = 0; i < (int)len; i++) BIO_printf(out, "%02x", buf[i]); BIO_printf(out, " *%s\n", file); } else { if (sig_name) { BIO_puts(out, sig_name); if (md_name) BIO_printf(out, "-%s", md_name); BIO_printf(out, "(%s)= ", file); } else if (md_name) BIO_printf(out, "%s(%s)= ", md_name, file); else BIO_printf(out, "(%s)= ", file); for (i = 0; i < (int)len; i++) { if (sep && (i != 0)) BIO_printf(out, ":"); BIO_printf(out, "%02x", buf[i]); } BIO_printf(out, "\n"); } return 0; }
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, non_fips_allow = 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_NON_FIPS_ALLOW: non_fips_allow = 1; 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 (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 (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\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", 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); } 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], bmd); 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); return (ret); }
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp, *mdc; int ret = 0, i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; EVP_MD_CTX_init(&mdc_tmp); if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type = OBJ_obj2nid(si->digest_alg->algorithm); btmp = bio; for (;;) { if ((btmp == NULL) || ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp, &mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; /* * Workaround for some broken clients that put the signature OID * instead of the digest OID in digest_alg->algorithm */ if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) break; btmp = BIO_next(btmp); } /* * mdc is the digest ctx that we want, unless there are attributes, in * which case the digest is the signed attributes */ if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) goto err; sk = si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len; int alen; ASN1_OCTET_STRING *message_digest; if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) goto err; message_digest = PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data, md_dat, md_len))) { #if 0 { int ii; for (ii = 0; ii < message_digest->length; ii++) printf("%02X", message_digest->data[ii]); printf(" sent\n"); for (ii = 0; ii < md_len; ii++) printf("%02X", md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret = -1; goto err; } if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); if (alen <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); ret = -1; goto err; } if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) goto err; OPENSSL_free(abuf); } os = si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret = -1; goto err; } else ret = 1; err: EVP_MD_CTX_cleanup(&mdc_tmp); return (ret); }
int dgst_main(int argc, char **argv) { ENGINE *e = 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; 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; #endif char *hmac_key = NULL; char *mac_name = NULL; STACK_OF(OPENSSL_STRING) * sigopts = NULL, *macopts = NULL; if ((buf = malloc(BUFSIZE)) == NULL) { BIO_printf(bio_err, "out of memory\n"); 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, "-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); } #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, "-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 (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, "-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; } 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 (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); } 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, e, 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 (hmac_key) { sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e, (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, NULL, sigkey); else r = EVP_DigestSignInit(mctx, &pctx, md, NULL, 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 { if (md == NULL) md = EVP_md5(); if (!BIO_set_md(bmd, md)) { BIO_printf(bio_err, "Error setting digest %s\n", pname); ERR_print_errors(bio_err); goto end; } } if (sigfile && sigkey) { BIO *sigbio; siglen = EVP_PKEY_size(sigkey); sigbuf = malloc(siglen); if (sigbuf == NULL) { BIO_printf(bio_err, "out of memory\n"); ERR_print_errors(bio_err); goto end; } 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 = 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); } 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); free(buf); } if (in != NULL) BIO_free(in); free(passin); BIO_free_all(out); EVP_PKEY_free(sigkey); if (sigopts) sk_OPENSSL_STRING_free(sigopts); if (macopts) sk_OPENSSL_STRING_free(macopts); free(sigbuf); if (bmd != NULL) BIO_free(bmd); return (err); }
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { int ret=0; int i,j; BIO *btmp; BUF_MEM *buf_mem=NULL; BUF_MEM *buf=NULL; PKCS7_SIGNER_INFO *si; EVP_MD_CTX *mdc,ctx_tmp; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; ASN1_OCTET_STRING *os=NULL; EVP_MD_CTX_init(&ctx_tmp); i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signedAndEnveloped: /* XXXXXXXXXXXXXXXX */ si_sk=p7->d.signed_and_enveloped->signer_info; os=M_ASN1_OCTET_STRING_new(); p7->d.signed_and_enveloped->enc_data->enc_data=os; break; case NID_pkcs7_enveloped: /* XXXXXXXXXXXXXXXX */ os=M_ASN1_OCTET_STRING_new(); p7->d.enveloped->enc_data->enc_data=os; break; case NID_pkcs7_signed: si_sk=p7->d.sign->signer_info; os=p7->d.sign->contents->d.data; /* If detached data then the content is excluded */ if(p7->detached) { M_ASN1_OCTET_STRING_free(os); p7->d.sign->contents->d.data = NULL; } break; } if (si_sk != NULL) { if ((buf=BUF_MEM_new()) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); goto err; } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { si=sk_PKCS7_SIGNER_INFO_value(si_sk,i); if (si->pkey == NULL) continue; j=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) { if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == j) break; else btmp=BIO_next(btmp); } /* We now have the EVP_MD_CTX, lets do the * signing. */ EVP_MD_CTX_copy_ex(&ctx_tmp,mdc); if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey))) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); goto err; } sk=si->auth_attr; /* If there are attributes, we add the digest * attribute and only sign the attributes */ if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *digest; ASN1_UTCTIME *sign_time; const EVP_MD *md_tmp; /* Add signing time if not already present */ if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { sign_time=X509_gmtime_adj(NULL,0); PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, V_ASN1_UTCTIME,sign_time); } /* Add digest */ md_tmp=EVP_MD_CTX_md(&ctx_tmp); EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len); digest=M_ASN1_OCTET_STRING_new(); M_ASN1_OCTET_STRING_set(digest,md_data,md_len); PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING,digest); /* Now sign the attributes */ EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL); alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); if(!abuf) goto err; EVP_SignUpdate(&ctx_tmp,abuf,alen); OPENSSL_free(abuf); } #ifndef OPENSSL_NO_DSA if (si->pkey->type == EVP_PKEY_DSA) ctx_tmp.digest=EVP_dss1(); #endif if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data, (unsigned int *)&buf->length,si->pkey)) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB); goto err; } if (!ASN1_STRING_set(si->enc_digest, (unsigned char *)buf->data,buf->length)) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB); goto err; } } } if (!PKCS7_is_detached(p7)) { btmp=BIO_find_type(bio,BIO_TYPE_MEM); if (btmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); goto err; } BIO_get_mem_ptr(btmp,&buf_mem); /* Mark the BIO read only then we can use its copy of the data * instead of making an extra copy. */ BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); BIO_set_mem_eof_return(btmp, 0); os->data = (unsigned char *)buf_mem->data; os->length = buf_mem->length; #if 0 M_ASN1_OCTET_STRING_set(os, (unsigned char *)buf_mem->data,buf_mem->length); #endif } ret=1; err: EVP_MD_CTX_cleanup(&ctx_tmp); if (buf != NULL) BUF_MEM_free(buf); return(ret); }
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title, const char *file,BIO *bmd,const char *hmac_key) { unsigned int len; int i; EVP_MD_CTX *md_ctx; HMAC_CTX hmac_ctx; if (hmac_key) { EVP_MD *md; BIO_get_md(bmd,&md); HMAC_CTX_init(&hmac_ctx); HMAC_Init_ex(&hmac_ctx,hmac_key,strlen(hmac_key),md, NULL); BIO_get_md_ctx(bmd,&md_ctx); BIO_set_md_ctx(bmd,&hmac_ctx.md_ctx); } for (;;) { i=BIO_read(bp,(char *)buf,BUFSIZE); if(i < 0) { BIO_printf(bio_err, "Read Error in %s\n",file); ERR_print_errors(bio_err); return 1; } if (i == 0) break; } if(sigin) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key); if(i > 0) BIO_printf(out, "Verified OK\n"); else if(i == 0) { BIO_printf(out, "Verification Failure\n"); return 1; } else { BIO_printf(bio_err, "Error Verifying Data\n"); ERR_print_errors(bio_err); return 1; } return 0; } if(key) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key)) { BIO_printf(bio_err, "Error Signing Data\n"); ERR_print_errors(bio_err); return 1; } } else if(hmac_key) { HMAC_Final(&hmac_ctx,buf,&len); HMAC_CTX_cleanup(&hmac_ctx); } else len=BIO_gets(bp,(char *)buf,BUFSIZE); if(binout) BIO_write(out, buf, len); else { BIO_write(out,title,strlen(title)); for (i=0; i<(int)len; i++) { if (sep && (i != 0)) BIO_printf(out, ":"); BIO_printf(out, "%02x",buf[i]); } BIO_printf(out, "\n"); } if (hmac_key) { BIO_set_md_ctx(bmd,md_ctx); } return 0; }
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp,*mdc; unsigned char *pp,*p; int ret=0,i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) { if ((btmp == NULL) || ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; btmp=BIO_next(btmp); } /* mdc is the digest ctx that we want, unless there are attributes, * in which case the digest is the signed attributes */ memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp)); sk=si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE]; unsigned int md_len; ASN1_OCTET_STRING *message_digest; EVP_DigestFinal(&mdc_tmp,md_dat,&md_len); message_digest=PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data,md_dat,md_len))) { #if 0 { int ii; for (ii=0; ii<message_digest->length; ii++) printf("%02X",message_digest->data[ii]); printf(" sent\n"); for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret= -1; goto err; } EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type)); /* Note: when forming the encoding of the attributes we * shouldn't reorder them or this will break the signature. * This is done by using the IS_SEQUENCE flag. */ i=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); pp=OPENSSL_malloc(i); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); EVP_VerifyUpdate(&mdc_tmp,pp,i); OPENSSL_free(pp); } os=si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } #ifndef NO_DSA if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); #endif i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret= -1; goto err; } else ret=1; err: return(ret); }