static VALUE ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) { VALUE pkey, cert, flags; EVP_PKEY *key; X509 *x509; int flg; PKCS7 *p7; BIO *out; VALUE str; rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ flg = NIL_P(flags) ? 0 : NUM2INT(flags); GetPKCS7(self, p7); if(!(out = BIO_new(BIO_s_mem()))) ossl_raise(ePKCS7Error, NULL); if(!PKCS7_decrypt(p7, key, x509, out, flg)){ BIO_free(out); ossl_raise(ePKCS7Error, NULL); } str = ossl_membio2str(out); /* out will be free */ return str; }
static LUA_FUNCTION(openssl_pkcs7_decrypt) { PKCS7 *p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7"); X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509"); EVP_PKEY *key = CHECK_OBJECT(3, EVP_PKEY, "openssl.evp_pkey"); long flags = luaL_optint(L, 4, 0); BIO *out = BIO_new(BIO_s_mem()); if (PKCS7_decrypt(p7, key, cert, out, flags)) { BUF_MEM* mem; BIO_get_mem_ptr(out, &mem); lua_pushlstring(L, mem->data, mem->length); } else lua_pushnil(L); BIO_free(out); return 1; }
int main(int argc, char **argv) { BIO *in = NULL, *out = NULL, *tbio = NULL; X509 *rcert = NULL; EVP_PKEY *rkey = NULL; PKCS7 *p7 = NULL; int ret = 1; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); /* Read in recipient certificate and private key */ tbio = BIO_new_file("signer.pem", "r"); if (!tbio) goto err; rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL); BIO_reset(tbio); rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); if (!rcert || !rkey) goto err; /* Open content being signed */ in = BIO_new_file("smencr.txt", "r"); if (!in) goto err; /* Sign content */ p7 = SMIME_read_PKCS7(in, NULL); if (!p7) goto err; out = BIO_new_file("encrout.txt", "w"); if (!out) goto err; /* Decrypt S/MIME message */ if (!PKCS7_decrypt(p7, rkey, rcert, out, 0)) goto err; ret = 0; err: if (ret) { fprintf(stderr, "Error Signing Data\n"); ERR_print_errors_fp(stderr); } PKCS7_free(p7); X509_free(rcert); EVP_PKEY_free(rkey); BIO_free(in); BIO_free(out); BIO_free(tbio); return ret; }
int smime_main(int argc, char **argv) { BIO *in = NULL, *out = NULL, *indata = NULL; EVP_PKEY *key = NULL; PKCS7 *p7 = NULL; STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; STACK_OF(X509) *encerts = NULL, *other = NULL; X509 *cert = NULL, *recip = NULL, *signer = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; const EVP_CIPHER *cipher = NULL; const EVP_MD *sign_md = NULL; const char *CAfile = NULL, *CApath = NULL, *prog = NULL; char *certfile = NULL, *keyfile = NULL, *contfile = NULL, *inrand = NULL; char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL; OPTION_CHOICE o; int noCApath = 0, noCAfile = 0; int flags = PKCS7_DETACHED, operation = 0, ret = 0, need_rand = 0, indef = 0; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = FORMAT_PEM; int vpmtouched = 0, rv = 0; ENGINE *e = NULL; const char *mime_eol = "\n"; if ((vpm = X509_VERIFY_PARAM_new()) == NULL) return 1; prog = opt_init(argc, argv, smime_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(smime_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_ENCRYPT: operation = SMIME_ENCRYPT; break; case OPT_DECRYPT: operation = SMIME_DECRYPT; break; case OPT_SIGN: operation = SMIME_SIGN; break; case OPT_RESIGN: operation = SMIME_RESIGN; break; case OPT_VERIFY: operation = SMIME_VERIFY; break; case OPT_PK7OUT: operation = SMIME_PK7OUT; break; case OPT_TEXT: flags |= PKCS7_TEXT; break; case OPT_NOINTERN: flags |= PKCS7_NOINTERN; break; case OPT_NOVERIFY: flags |= PKCS7_NOVERIFY; break; case OPT_NOCHAIN: flags |= PKCS7_NOCHAIN; break; case OPT_NOCERTS: flags |= PKCS7_NOCERTS; break; case OPT_NOATTR: flags |= PKCS7_NOATTR; break; case OPT_NODETACH: flags &= ~PKCS7_DETACHED; break; case OPT_NOSMIMECAP: flags |= PKCS7_NOSMIMECAP; break; case OPT_BINARY: flags |= PKCS7_BINARY; break; case OPT_NOSIGS: flags |= PKCS7_NOSIGS; break; case OPT_STREAM: case OPT_INDEF: indef = 1; break; case OPT_NOINDEF: indef = 0; break; case OPT_CRLFEOL: flags |= PKCS7_CRLFEOL; mime_eol = "\r\n"; break; case OPT_RAND: inrand = opt_arg(); need_rand = 1; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_TO: to = opt_arg(); break; case OPT_FROM: from = opt_arg(); break; case OPT_SUBJECT: subject = opt_arg(); break; case OPT_SIGNER: /* If previous -signer argument add signer to list */ if (signerfile) { if (sksigners == NULL && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); if (keyfile == NULL) keyfile = signerfile; if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) goto end; sk_OPENSSL_STRING_push(skkeys, keyfile); keyfile = NULL; } signerfile = opt_arg(); break; case OPT_RECIP: recipfile = opt_arg(); break; case OPT_MD: if (!opt_md(opt_arg(), &sign_md)) goto opthelp; break; case OPT_CIPHER: if (!opt_cipher(opt_unknown(), &cipher)) goto opthelp; break; case OPT_INKEY: /* If previous -inkey argument add signer to list */ if (keyfile) { if (signerfile == NULL) { BIO_printf(bio_err, "%s: Must have -signer before -inkey\n", prog); goto opthelp; } if (sksigners == NULL && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); signerfile = NULL; if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) goto end; sk_OPENSSL_STRING_push(skkeys, keyfile); } keyfile = opt_arg(); break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) goto opthelp; break; case OPT_CERTFILE: certfile = opt_arg(); break; case OPT_CAFILE: CAfile = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_CONTENT: contfile = opt_arg(); break; case OPT_V_CASES: if (!opt_verify(o, vpm)) goto opthelp; vpmtouched++; break; } } argc = opt_num_rest(); argv = opt_rest(); if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); goto opthelp; } if (operation & SMIME_SIGNERS) { /* Check to see if any final signer needs to be appended */ if (keyfile && !signerfile) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); goto opthelp; } if (signerfile) { if (!sksigners && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) goto end; if (!keyfile) keyfile = signerfile; sk_OPENSSL_STRING_push(skkeys, keyfile); } if (!sksigners) { BIO_printf(bio_err, "No signer certificate specified\n"); goto opthelp; } signerfile = NULL; keyfile = NULL; need_rand = 1; } else if (operation == SMIME_DECRYPT) { if (!recipfile && !keyfile) { BIO_printf(bio_err, "No recipient certificate or key specified\n"); goto opthelp; } } else if (operation == SMIME_ENCRYPT) { if (argc == 0) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); goto opthelp; } need_rand = 1; } else if (!operation) goto opthelp; if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (need_rand) { app_RAND_load_file(NULL, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err, "%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } ret = 2; if (!(operation & SMIME_SIGNERS)) flags &= ~PKCS7_DETACHED; if (!(operation & SMIME_OP)) { if (flags & PKCS7_BINARY) outformat = FORMAT_BINARY; } if (!(operation & SMIME_IP)) { if (flags & PKCS7_BINARY) informat = FORMAT_BINARY; } if (operation == SMIME_ENCRYPT) { if (!cipher) { #ifndef OPENSSL_NO_DES cipher = EVP_des_ede3_cbc(); #else BIO_printf(bio_err, "No cipher selected\n"); goto end; #endif } encerts = sk_X509_new_null(); if (!encerts) goto end; while (*argv) { cert = load_cert(*argv, FORMAT_PEM, "recipient certificate file"); if (cert == NULL) goto end; sk_X509_push(encerts, cert); cert = NULL; argv++; } } if (certfile) { if (!load_certs(certfile, &other, FORMAT_PEM, NULL, "certificate file")) { ERR_print_errors(bio_err); goto end; } } if (recipfile && (operation == SMIME_DECRYPT)) { if ((recip = load_cert(recipfile, FORMAT_PEM, "recipient certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; } } if (operation == SMIME_DECRYPT) { if (!keyfile) keyfile = recipfile; } else if (operation == SMIME_SIGN) { if (!keyfile) keyfile = signerfile; } else keyfile = NULL; if (keyfile) { key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); if (!key) goto end; } in = bio_open_default(infile, 'r', informat); if (in == NULL) goto end; if (operation & SMIME_IP) { if (informat == FORMAT_SMIME) p7 = SMIME_read_PKCS7(in, &indata); else if (informat == FORMAT_PEM) p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); else if (informat == FORMAT_ASN1) p7 = d2i_PKCS7_bio(in, NULL); else { BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); goto end; } if (!p7) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } if (contfile) { BIO_free(indata); if ((indata = BIO_new_file(contfile, "rb")) == NULL) { BIO_printf(bio_err, "Can't read content file %s\n", contfile); goto end; } } } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (operation == SMIME_VERIFY) { if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; X509_STORE_set_verify_cb(store, smime_cb); if (vpmtouched) X509_STORE_set1_param(store, vpm); } ret = 3; if (operation == SMIME_ENCRYPT) { if (indef) flags |= PKCS7_STREAM; p7 = PKCS7_encrypt(encerts, in, cipher, flags); } else if (operation & SMIME_SIGNERS) { int i; /* * If detached data content we only enable streaming if S/MIME output * format. */ if (operation == SMIME_SIGN) { if (flags & PKCS7_DETACHED) { if (outformat == FORMAT_SMIME) flags |= PKCS7_STREAM; } else if (indef) flags |= PKCS7_STREAM; flags |= PKCS7_PARTIAL; p7 = PKCS7_sign(NULL, NULL, other, in, flags); if (!p7) goto end; if (flags & PKCS7_NOCERTS) { for (i = 0; i < sk_X509_num(other); i++) { X509 *x = sk_X509_value(other, i); PKCS7_add_certificate(p7, x); } } } else flags |= PKCS7_REUSE_DIGEST; for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); signer = load_cert(signerfile, FORMAT_PEM, "signer certificate"); if (!signer) goto end; key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); if (!key) goto end; if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) goto end; X509_free(signer); signer = NULL; EVP_PKEY_free(key); key = NULL; } /* If not streaming or resigning finalize structure */ if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { if (!PKCS7_final(p7, in, flags)) goto end; } } if (!p7) { BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); goto end; } ret = 4; if (operation == SMIME_DECRYPT) { if (!PKCS7_decrypt(p7, key, recip, out, flags)) { BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); goto end; } } else if (operation == SMIME_VERIFY) { STACK_OF(X509) *signers; if (PKCS7_verify(p7, other, store, indata, out, flags)) BIO_printf(bio_err, "Verification successful\n"); else { BIO_printf(bio_err, "Verification failure\n"); goto end; } signers = PKCS7_get0_signers(p7, other, flags); if (!save_certs(signerfile, signers)) { BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); ret = 5; goto end; } sk_X509_free(signers); } else if (operation == SMIME_PK7OUT) PEM_write_bio_PKCS7(out, p7); else { if (to) BIO_printf(out, "To: %s%s", to, mime_eol); if (from) BIO_printf(out, "From: %s%s", from, mime_eol); if (subject) BIO_printf(out, "Subject: %s%s", subject, mime_eol); if (outformat == FORMAT_SMIME) { if (operation == SMIME_RESIGN) rv = SMIME_write_PKCS7(out, p7, indata, flags); else rv = SMIME_write_PKCS7(out, p7, in, flags); } else if (outformat == FORMAT_PEM) rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags); else if (outformat == FORMAT_ASN1) rv = i2d_PKCS7_bio_stream(out, p7, in, flags); else { BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); goto end; } if (rv == 0) { BIO_printf(bio_err, "Error writing output\n"); ret = 3; goto end; } } ret = 0; end: if (need_rand) app_RAND_write_file(NULL); if (ret) ERR_print_errors(bio_err); sk_X509_pop_free(encerts, X509_free); sk_X509_pop_free(other, X509_free); X509_VERIFY_PARAM_free(vpm); sk_OPENSSL_STRING_free(sksigners); sk_OPENSSL_STRING_free(skkeys); X509_STORE_free(store); X509_free(cert); X509_free(recip); X509_free(signer); EVP_PKEY_free(key); PKCS7_free(p7); release_engine(e); BIO_free(in); BIO_free(indata); BIO_free_all(out); OPENSSL_free(passin); return (ret); }
/******************************************************************************* 函数名称: cert_pkcs7_unwrap 功能描述: 解析从服务器收到的信息,包括验证签名以及解密。 输入参数: struct scep *s, SCEP操作的结构体指针。 输出参数: 无 返 回 值: 1,成功;-1,失败 -------------------------------------------------------------------------------- 最近一次修改记录: 修改作者:王朝 修改目的:添加新函数 修改日期:2009年12月28日 *********************************************************************************/ s32 cert_pkcs7_unwrap(struct scep *s) { BIO *memorybio = NULL; BIO *outbio = NULL; BIO *pkcs7bio = NULL; s32 bytes, used, retval = -1; STACK_OF(PKCS7_SIGNER_INFO) *sk = NULL; PKCS7 *p7enc = NULL; PKCS7_SIGNER_INFO *si = NULL; STACK_OF(X509_ATTRIBUTE) *attribs = NULL; s8 *p = NULL; u8 buffer[1024]; X509 *recipientcert = NULL; EVP_PKEY *recipientkey = NULL; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if ((BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0) { goto end; } BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL); BIO_free(memorybio); memorybio = NULL; /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { goto end; } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL); if (pkcs7bio == NULL) { goto end; } /* */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } (void)BIO_flush(outbio); /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL) { goto end; } /* Verify signature */ si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cert_cacert) <= 0) { goto end; } /* Get signed attributes */ attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL) { goto end; } /* Transaction id */ if (1 != cert_get_signed_attribute(attribs, nid_transId, V_ASN1_PRINTABLESTRING, &p)) { goto end; } if (strncmp(s->transaction_id, p, strlen(p))) { goto end; } /* Message type, should be of type CertRep */ if (1 != cert_get_signed_attribute(attribs, nid_messageType, V_ASN1_PRINTABLESTRING, &p)) { goto end; } if (atoi(p) != 3) { goto end; } /* Sender and recipient nonces: */ if (1 == cert_get_signed_attribute(attribs, nid_senderNonce, V_ASN1_OCTET_STRING, &p)) { s->reply_sender_nonce = (u8 *)p; } else { s->reply_sender_nonce = NULL; } if ( 1 != cert_get_signed_attribute(attribs, nid_recipientNonce,V_ASN1_OCTET_STRING, &p)) { goto end; } s->reply_recipient_nonce = (u8 *)p; /* Get pkiStatus */ if (1 != cert_get_signed_attribute(attribs, nid_pkiStatus,V_ASN1_PRINTABLESTRING, &p)) { goto end; } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: s->pki_status = SCEP_PKISTATUS_PENDING; break; default: goto end; } /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if (1 != cert_get_signed_attribute(attribs, nid_failInfo,V_ASN1_PRINTABLESTRING, &p)) { goto end; } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; break; default: goto end; } } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ retval = 1; goto end; } /* We got success and expect data */ if (used == 0) { goto end; } /* Decrypt the inner PKCS#7 */ if ((s->request_type == SCEP_REQUEST_PKCSREQ) || (s->request_type == SCEP_REQUEST_GETCERTINIT)) { recipientcert = s->signercert; recipientkey = s->signerkey; } else { recipientcert = cert_localcert; recipientkey = cert_rsa; } p7enc = d2i_PKCS7_bio(outbio, NULL); if (p7enc == NULL) { goto end; } BIO_free(outbio); outbio = NULL; /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { goto end; } (void)BIO_flush(outbio); /* Write decrypted data */ s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload); BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL); retval = 1; end: if(NULL != outbio) { BIO_free(outbio); } if(NULL != memorybio) { BIO_free(memorybio); } if(NULL != pkcs7bio) { BIO_free(pkcs7bio); } if(NULL != p7enc) { PKCS7_free(p7enc); } return retval; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; int operation = 0; int ret = 0; char **args; const char *inmode = "r", *outmode = "w"; char *infile = NULL, *outfile = NULL; char *signerfile = NULL, *recipfile = NULL; char *certfile = NULL, *keyfile = NULL, *contfile=NULL; const EVP_CIPHER *cipher = NULL; PKCS7 *p7 = NULL; X509_STORE *store = NULL; X509 *cert = NULL, *recip = NULL, *signer = NULL; EVP_PKEY *key = NULL; STACK_OF(X509) *encerts = NULL, *other = NULL; BIO *in = NULL, *out = NULL, *indata = NULL; int badarg = 0; int flags = PKCS7_DETACHED; char *to = NULL, *from = NULL, *subject = NULL; char *CAfile = NULL, *CApath = NULL; char *passargin = NULL, *passin = NULL; char *inrand = NULL; int need_rand = 0; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; int keyform = FORMAT_PEM; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif X509_VERIFY_PARAM *vpm = NULL; args = argv + 1; ret = 1; apps_startup(); 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; while (!badarg && *args && *args[0] == '-') { if (!strcmp (*args, "-encrypt")) operation = SMIME_ENCRYPT; else if (!strcmp (*args, "-decrypt")) operation = SMIME_DECRYPT; else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN; else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY; else if (!strcmp (*args, "-pk7out")) operation = SMIME_PK7OUT; #ifndef OPENSSL_NO_DES else if (!strcmp (*args, "-des3")) cipher = EVP_des_ede3_cbc(); else if (!strcmp (*args, "-des")) cipher = EVP_des_cbc(); #endif #ifndef OPENSSL_NO_SEED else if (!strcmp (*args, "-seed")) cipher = EVP_seed_cbc(); #endif #ifndef OPENSSL_NO_RC2 else if (!strcmp (*args, "-rc2-40")) cipher = EVP_rc2_40_cbc(); else if (!strcmp (*args, "-rc2-128")) cipher = EVP_rc2_cbc(); else if (!strcmp (*args, "-rc2-64")) cipher = EVP_rc2_64_cbc(); #endif #ifndef OPENSSL_NO_AES else if (!strcmp(*args,"-aes128")) cipher = EVP_aes_128_cbc(); else if (!strcmp(*args,"-aes192")) cipher = EVP_aes_192_cbc(); else if (!strcmp(*args,"-aes256")) cipher = EVP_aes_256_cbc(); #endif #ifndef OPENSSL_NO_CAMELLIA else if (!strcmp(*args,"-camellia128")) cipher = EVP_camellia_128_cbc(); else if (!strcmp(*args,"-camellia192")) cipher = EVP_camellia_192_cbc(); else if (!strcmp(*args,"-camellia256")) cipher = EVP_camellia_256_cbc(); #endif else if (!strcmp (*args, "-text")) flags |= PKCS7_TEXT; else if (!strcmp (*args, "-nointern")) flags |= PKCS7_NOINTERN; else if (!strcmp (*args, "-noverify")) flags |= PKCS7_NOVERIFY; else if (!strcmp (*args, "-nochain")) flags |= PKCS7_NOCHAIN; else if (!strcmp (*args, "-nocerts")) flags |= PKCS7_NOCERTS; else if (!strcmp (*args, "-noattr")) flags |= PKCS7_NOATTR; else if (!strcmp (*args, "-nodetach")) flags &= ~PKCS7_DETACHED; else if (!strcmp (*args, "-nosmimecap")) flags |= PKCS7_NOSMIMECAP; else if (!strcmp (*args, "-binary")) flags |= PKCS7_BINARY; else if (!strcmp (*args, "-nosigs")) flags |= PKCS7_NOSIGS; else if (!strcmp (*args, "-nooldmime")) flags |= PKCS7_NOOLDMIMETYPE; else if (!strcmp (*args, "-crlfeol")) flags |= PKCS7_CRLFEOL; else if (!strcmp(*args,"-rand")) { if (args[1]) { args++; inrand = *args; } else badarg = 1; need_rand = 1; } #ifndef OPENSSL_NO_ENGINE else if (!strcmp(*args,"-engine")) { if (args[1]) { args++; engine = *args; } else badarg = 1; } #endif else if (!strcmp(*args,"-passin")) { if (args[1]) { args++; passargin = *args; } else badarg = 1; } else if (!strcmp (*args, "-to")) { if (args[1]) { args++; to = *args; } else badarg = 1; } else if (!strcmp (*args, "-from")) { if (args[1]) { args++; from = *args; } else badarg = 1; } else if (!strcmp (*args, "-subject")) { if (args[1]) { args++; subject = *args; } else badarg = 1; } else if (!strcmp (*args, "-signer")) { if (args[1]) { args++; signerfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-recip")) { if (args[1]) { args++; recipfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-inkey")) { if (args[1]) { args++; keyfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-keyform")) { if (args[1]) { args++; keyform = str2fmt(*args); } else badarg = 1; } else if (!strcmp (*args, "-certfile")) { if (args[1]) { args++; certfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-CAfile")) { if (args[1]) { args++; CAfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-CApath")) { if (args[1]) { args++; CApath = *args; } else badarg = 1; } else if (!strcmp (*args, "-in")) { if (args[1]) { args++; infile = *args; } else badarg = 1; } else if (!strcmp (*args, "-inform")) { if (args[1]) { args++; informat = str2fmt(*args); } else badarg = 1; } else if (!strcmp (*args, "-outform")) { if (args[1]) { args++; outformat = str2fmt(*args); } else badarg = 1; } else if (!strcmp (*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-content")) { if (args[1]) { args++; contfile = *args; } else badarg = 1; } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) continue; else badarg = 1; args++; } if (operation == SMIME_SIGN) { if (!signerfile) { BIO_printf(bio_err, "No signer certificate specified\n"); badarg = 1; } need_rand = 1; } else if (operation == SMIME_DECRYPT) { if (!recipfile && !keyfile) { BIO_printf(bio_err, "No recipient certificate or key specified\n"); badarg = 1; } } else if (operation == SMIME_ENCRYPT) { if (!*args) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); badarg = 1; } need_rand = 1; } else if (!operation) badarg = 1; if (badarg) { BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); BIO_printf (bio_err, "where options are\n"); BIO_printf (bio_err, "-encrypt encrypt message\n"); BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); BIO_printf (bio_err, "-sign sign message\n"); BIO_printf (bio_err, "-verify verify signed message\n"); BIO_printf (bio_err, "-pk7out output PKCS#7 structure\n"); #ifndef OPENSSL_NO_DES BIO_printf (bio_err, "-des3 encrypt with triple DES\n"); BIO_printf (bio_err, "-des encrypt with DES\n"); #endif #ifndef OPENSSL_NO_SEED BIO_printf (bio_err, "-seed encrypt with SEED\n"); #endif #ifndef OPENSSL_NO_RC2 BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n"); BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n"); #endif #ifndef OPENSSL_NO_AES BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); #endif #ifndef OPENSSL_NO_CAMELLIA BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n"); BIO_printf (bio_err, " encrypt PEM output with cbc camellia\n"); #endif BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n"); BIO_printf (bio_err, "-nosigs don't verify message signature\n"); BIO_printf (bio_err, "-noverify don't verify signers certificate\n"); BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n"); BIO_printf (bio_err, "-nodetach use opaque signing\n"); BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); BIO_printf (bio_err, "-binary don't translate message to text\n"); BIO_printf (bio_err, "-certfile file other certificates file\n"); BIO_printf (bio_err, "-signer file signer certificate file\n"); BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); BIO_printf (bio_err, "-in file input file\n"); BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); BIO_printf (bio_err, "-out file output file\n"); BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); BIO_printf (bio_err, "-content file supply or override content for detached signature\n"); BIO_printf (bio_err, "-to addr to address\n"); BIO_printf (bio_err, "-from ad from address\n"); BIO_printf (bio_err, "-subject s subject\n"); BIO_printf (bio_err, "-text include or delete text MIME headers\n"); BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf (bio_err, "-passin arg input file pass phrase source\n"); BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); BIO_printf(bio_err, " the random number generator\n"); BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n"); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (need_rand) { app_RAND_load_file(NULL, bio_err, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } ret = 2; if (operation != SMIME_SIGN) flags &= ~PKCS7_DETACHED; if (operation & SMIME_OP) { if (flags & PKCS7_BINARY) inmode = "rb"; if (outformat == FORMAT_ASN1) outmode = "wb"; } else { if (flags & PKCS7_BINARY) outmode = "wb"; if (informat == FORMAT_ASN1) inmode = "rb"; } if (operation == SMIME_ENCRYPT) { if (!cipher) { #ifndef OPENSSL_NO_RC2 cipher = EVP_rc2_40_cbc(); #else BIO_printf(bio_err, "No cipher selected\n"); goto end; #endif } encerts = sk_X509_new_null(); while (*args) { if (!(cert = load_cert(bio_err,*args,FORMAT_PEM, NULL, e, "recipient certificate file"))) { #if 0 /* An appropriate message is already printed */ BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); #endif goto end; } sk_X509_push(encerts, cert); cert = NULL; args++; } } if (signerfile && (operation == SMIME_SIGN)) { if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, e, "signer certificate"))) { #if 0 /* An appropri message has already been printed */ BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); #endif goto end; } } if (certfile) { if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, e, "certificate file"))) { #if 0 /* An appropriate message has already been printed */ BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); #endif ERR_print_errors(bio_err); goto end; } } if (recipfile && (operation == SMIME_DECRYPT)) { if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, e, "recipient certificate file"))) { #if 0 /* An appropriate message has alrady been printed */ BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); #endif ERR_print_errors(bio_err); goto end; } } if (operation == SMIME_DECRYPT) { if (!keyfile) keyfile = recipfile; } else if (operation == SMIME_SIGN) { if (!keyfile) keyfile = signerfile; } else keyfile = NULL; if (keyfile) { key = load_key(bio_err, keyfile, keyform, 0, passin, e, "signing key file"); if (!key) goto end; } if (infile) { if (!(in = BIO_new_file(infile, inmode))) { BIO_printf (bio_err, "Can't open input file %s\n", infile); goto end; } } else in = BIO_new_fp(stdin, BIO_NOCLOSE); if (outfile) { if (!(out = BIO_new_file(outfile, outmode))) { BIO_printf (bio_err, "Can't open output file %s\n", outfile); 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 (operation == SMIME_VERIFY) { if (!(store = setup_verify(bio_err, CAfile, CApath))) goto end; X509_STORE_set_verify_cb_func(store, smime_cb); if (vpm) X509_STORE_set1_param(store, vpm); } ret = 3; if (operation == SMIME_ENCRYPT) p7 = PKCS7_encrypt(encerts, in, cipher, flags); else if (operation == SMIME_SIGN) { /* If detached data and SMIME output enable partial * signing. */ if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME)) flags |= PKCS7_STREAM; p7 = PKCS7_sign(signer, key, other, in, flags); } else { if (informat == FORMAT_SMIME) p7 = SMIME_read_PKCS7(in, &indata); else if (informat == FORMAT_PEM) p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); else if (informat == FORMAT_ASN1) p7 = d2i_PKCS7_bio(in, NULL); else { BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); goto end; } if (!p7) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } if (contfile) { BIO_free(indata); if (!(indata = BIO_new_file(contfile, "rb"))) { BIO_printf(bio_err, "Can't read content file %s\n", contfile); goto end; } } } if (!p7) { BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); goto end; } ret = 4; if (operation == SMIME_DECRYPT) { if (!PKCS7_decrypt(p7, key, recip, out, flags)) { BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); goto end; } } else if (operation == SMIME_VERIFY) { STACK_OF(X509) *signers; if (PKCS7_verify(p7, other, store, indata, out, flags)) BIO_printf(bio_err, "Verification successful\n"); else { BIO_printf(bio_err, "Verification failure\n"); goto end; } signers = PKCS7_get0_signers(p7, other, flags); if (!save_certs(signerfile, signers)) { BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); ret = 5; goto end; } sk_X509_free(signers); } else if (operation == SMIME_PK7OUT) PEM_write_bio_PKCS7(out, p7); else { if (to) BIO_printf(out, "To: %s\n", to); if (from) BIO_printf(out, "From: %s\n", from); if (subject) BIO_printf(out, "Subject: %s\n", subject); if (outformat == FORMAT_SMIME) SMIME_write_PKCS7(out, p7, in, flags); else if (outformat == FORMAT_PEM) PEM_write_bio_PKCS7(out,p7); else if (outformat == FORMAT_ASN1) i2d_PKCS7_bio(out,p7); else { BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); goto end; } } ret = 0; end: if (need_rand) app_RAND_write_file(NULL, bio_err); if (ret) ERR_print_errors(bio_err); sk_X509_pop_free(encerts, X509_free); sk_X509_pop_free(other, X509_free); if (vpm) X509_VERIFY_PARAM_free(vpm); X509_STORE_free(store); X509_free(cert); X509_free(recip); X509_free(signer); EVP_PKEY_free(key); PKCS7_free(p7); BIO_free(in); BIO_free(indata); BIO_free_all(out); if (passin) OPENSSL_free(passin); return (ret); }
/* * Unwrap PKCS#7 data and decrypt if necessary */ int pkcs7_unwrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info, char* data, int datalen) { BIO *memorybio = NULL; BIO *outbio = NULL; BIO *pkcs7bio = NULL; int i, bytes, used; STACK_OF(PKCS7_SIGNER_INFO) *sk; PKCS7 *p7enc = NULL; PKCS7_SIGNER_INFO *si; STACK_OF(X509_ATTRIBUTE) *attribs; char *p = NULL; unsigned char buffer[1024]; X509 *recipientcert; EVP_PKEY *recipientkey; int ret = SCEP_PKISTATUS_P7; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if (ctx->verbose){ qeo_log_i("reading outer PKCS#7"); } if (BIO_write(memorybio, data, datalen) <= 0) { qeo_log_e("error reading PKCS#7 data"); goto error; } if (ctx->verbose){ qeo_log_i("PKCS#7 payload size: %d bytes", datalen); } s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL ); if (s->reply_p7 == NULL ) { qeo_log_e("error retrieving PKCS#7 data"); goto error; } if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, s->reply_p7); } /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { qeo_log_e("PKCS#7 is not signed!"); goto error; } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL ); if (pkcs7bio == NULL ) { qeo_log_e("cannot get PKCS#7 data"); goto error; } /* Copy enveloped data from PKCS#7 */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } (void)BIO_flush(outbio); if (ctx->verbose){ qeo_log_i("PKCS#7 contains %d bytes of enveloped data", used); } /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL ) { qeo_log_e("cannot get signer info!"); goto error; } /* Verify signature */ if (ctx->verbose){ qeo_log_i("verifying signature"); } si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, op_info->racert) <= 0) { qeo_log_e("error verifying signature"); goto error; } if (ctx->verbose){ qeo_log_i("signature ok"); } /* Get signed attributes */ if (ctx->verbose){ qeo_log_i("finding signed attributes"); } attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL ) { qeo_log_e("no attributes found"); goto error; } /* Transaction id */ if ((get_signed_attribute(attribs, ctx->nid_transId, V_ASN1_PRINTABLESTRING, &p, ctx)) == 1) { qeo_log_e("cannot find transId"); goto error; } if (ctx->verbose){ qeo_log_i("reply transaction id: %s", p); } if (strncmp(s->transaction_id, p, strlen(p))) { qeo_log_e("transaction id mismatch"); goto error; } free(p); p=NULL; /* Message type, should be of type CertRep */ if (get_signed_attribute(attribs, ctx->nid_messageType, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find messageType"); goto error; } if (atoi(p) != 3) { qeo_log_e("wrong message type in reply"); goto error; } if (ctx->verbose){ qeo_log_i("reply message type is good"); } free(p); p=NULL; /* Recipient nonces: */ if (get_signed_attribute(attribs, ctx->nid_recipientNonce, V_ASN1_OCTET_STRING, &p, ctx) == 1) { qeo_log_e("cannot find recipientNonce"); goto error; } s->reply_recipient_nonce = p; p = NULL; if (ctx->verbose) { qeo_log_i("recipientNonce in reply"); } /* * Compare recipient nonce to original sender nonce * The draft says nothing about this, but it makes sense to me.. * XXXXXXXXXXXXXX check */ for (i = 0; i < 16; i++) { if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) { if (ctx->verbose) qeo_log_e("corrupted nonce received"); /* Instead of exit, break out */ break; } } /* Get pkiStatus */ if (get_signed_attribute(attribs, ctx->nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find pkiStatus"); /* This is a mandatory attribute.. */ goto error; } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: qeo_log_i("pkistatus: SUCCESS"); s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: qeo_log_i("pkistatus: FAILURE"); s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: qeo_log_i("pkistatus: PENDING"); s->pki_status = SCEP_PKISTATUS_PENDING; break; default: qeo_log_e("wrong pkistatus in reply"); goto error; } free(p); p=NULL; /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if (get_signed_attribute(attribs, ctx->nid_failInfo, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find failInfo"); goto error; } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; qeo_log_i("reason: %s", SCEP_FAILINFO_BADALG_STR); break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; qeo_log_i("reason: %s", SCEP_FAILINFO_BADMSGCHK_STR); break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; qeo_log_i("reason: %s", SCEP_FAILINFO_BADREQ_STR); break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; qeo_log_i("reason: %s", SCEP_FAILINFO_BADTIME_STR); break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; qeo_log_i("reason: %s", SCEP_FAILINFO_BADCERTID_STR); break; default: qeo_log_e("wrong failInfo in " "reply"); goto error; } free(p); p=NULL; } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ if (ctx->verbose && (used != 0)) { qeo_log_e("illegal size of payload"); } return (0); } /* We got success and expect data */ if (used == 0) { qeo_log_e("illegal size of payload"); goto error; } /* Decrypt the inner PKCS#7 */ recipientcert = s->signercert; recipientkey = s->signerkey; if (ctx->verbose){ qeo_log_i("reading inner PKCS#7"); } p7enc = d2i_PKCS7_bio(outbio, NULL ); if (p7enc == NULL ) { qeo_log_e("cannot read inner PKCS#7"); goto error; } BIO_free(outbio);/* No longer need it */ outbio = NULL; if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, p7enc); } /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (ctx->verbose){ qeo_log_i("decrypting inner PKCS#7"); } if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { qeo_log_e("error decrypting inner PKCS#7"); goto error; } (void)BIO_flush(outbio); /* Write decrypted data */ PKCS7_free(s->reply_p7); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL ); ret = 0; error: free(p); BIO_free(outbio); BIO_free_all(pkcs7bio); BIO_free(memorybio); PKCS7_free(p7enc); return ret; }
int smime_main(int argc, char **argv) { ENGINE *e = NULL; int operation = 0; int ret = 0; char **args; const char *inmode = "r", *outmode = "w"; char *infile = NULL, *outfile = NULL; char *signerfile = NULL, *recipfile = NULL; STACK_OF(OPENSSL_STRING) * sksigners = NULL, *skkeys = NULL; char *certfile = NULL, *keyfile = NULL, *contfile = NULL; const EVP_CIPHER *cipher = NULL; PKCS7 *p7 = NULL; X509_STORE *store = NULL; X509 *cert = NULL, *recip = NULL, *signer = NULL; EVP_PKEY *key = NULL; STACK_OF(X509) * encerts = NULL, *other = NULL; BIO *in = NULL, *out = NULL, *indata = NULL; int badarg = 0; int flags = PKCS7_DETACHED; char *to = NULL, *from = NULL, *subject = NULL; char *CAfile = NULL, *CApath = NULL; char *passargin = NULL, *passin = NULL; int indef = 0; const EVP_MD *sign_md = NULL; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; int keyform = FORMAT_PEM; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif X509_VERIFY_PARAM *vpm = NULL; args = argv + 1; ret = 1; while (!badarg && *args && *args[0] == '-') { if (!strcmp(*args, "-encrypt")) operation = SMIME_ENCRYPT; else if (!strcmp(*args, "-decrypt")) operation = SMIME_DECRYPT; else if (!strcmp(*args, "-sign")) operation = SMIME_SIGN; else if (!strcmp(*args, "-resign")) operation = SMIME_RESIGN; else if (!strcmp(*args, "-verify")) operation = SMIME_VERIFY; else if (!strcmp(*args, "-pk7out")) operation = SMIME_PK7OUT; #ifndef OPENSSL_NO_DES else if (!strcmp(*args, "-des3")) cipher = EVP_des_ede3_cbc(); else if (!strcmp(*args, "-des")) cipher = EVP_des_cbc(); #endif #ifndef OPENSSL_NO_RC2 else if (!strcmp(*args, "-rc2-40")) cipher = EVP_rc2_40_cbc(); else if (!strcmp(*args, "-rc2-128")) cipher = EVP_rc2_cbc(); else if (!strcmp(*args, "-rc2-64")) cipher = EVP_rc2_64_cbc(); #endif #ifndef OPENSSL_NO_AES else if (!strcmp(*args, "-aes128")) cipher = EVP_aes_128_cbc(); else if (!strcmp(*args, "-aes192")) cipher = EVP_aes_192_cbc(); else if (!strcmp(*args, "-aes256")) cipher = EVP_aes_256_cbc(); #endif #ifndef OPENSSL_NO_CAMELLIA else if (!strcmp(*args, "-camellia128")) cipher = EVP_camellia_128_cbc(); else if (!strcmp(*args, "-camellia192")) cipher = EVP_camellia_192_cbc(); else if (!strcmp(*args, "-camellia256")) cipher = EVP_camellia_256_cbc(); #endif else if (!strcmp(*args, "-text")) flags |= PKCS7_TEXT; else if (!strcmp(*args, "-nointern")) flags |= PKCS7_NOINTERN; else if (!strcmp(*args, "-noverify")) flags |= PKCS7_NOVERIFY; else if (!strcmp(*args, "-nochain")) flags |= PKCS7_NOCHAIN; else if (!strcmp(*args, "-nocerts")) flags |= PKCS7_NOCERTS; else if (!strcmp(*args, "-noattr")) flags |= PKCS7_NOATTR; else if (!strcmp(*args, "-nodetach")) flags &= ~PKCS7_DETACHED; else if (!strcmp(*args, "-nosmimecap")) flags |= PKCS7_NOSMIMECAP; else if (!strcmp(*args, "-binary")) flags |= PKCS7_BINARY; else if (!strcmp(*args, "-nosigs")) flags |= PKCS7_NOSIGS; else if (!strcmp(*args, "-stream")) indef = 1; else if (!strcmp(*args, "-indef")) indef = 1; else if (!strcmp(*args, "-noindef")) indef = 0; else if (!strcmp(*args, "-nooldmime")) flags |= PKCS7_NOOLDMIMETYPE; else if (!strcmp(*args, "-crlfeol")) flags |= PKCS7_CRLFEOL; #ifndef OPENSSL_NO_ENGINE else if (!strcmp(*args, "-engine")) { if (!args[1]) goto argerr; engine = *++args; } #endif else if (!strcmp(*args, "-passin")) { if (!args[1]) goto argerr; passargin = *++args; } else if (!strcmp(*args, "-to")) { if (!args[1]) goto argerr; to = *++args; } else if (!strcmp(*args, "-from")) { if (!args[1]) goto argerr; from = *++args; } else if (!strcmp(*args, "-subject")) { if (!args[1]) goto argerr; subject = *++args; } else if (!strcmp(*args, "-signer")) { if (!args[1]) goto argerr; /* If previous -signer argument add signer to list */ if (signerfile) { if (!sksigners) sksigners = sk_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_push(sksigners, signerfile); if (!keyfile) keyfile = signerfile; if (!skkeys) skkeys = sk_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_push(skkeys, keyfile); keyfile = NULL; } signerfile = *++args; } else if (!strcmp(*args, "-recip")) { if (!args[1]) goto argerr; recipfile = *++args; } else if (!strcmp(*args, "-md")) { if (!args[1]) goto argerr; sign_md = EVP_get_digestbyname(*++args); if (sign_md == NULL) { BIO_printf(bio_err, "Unknown digest %s\n", *args); goto argerr; } } else if (!strcmp(*args, "-inkey")) { if (!args[1]) goto argerr; /* If previous -inkey arument add signer to list */ if (keyfile) { if (!signerfile) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); goto argerr; } if (!sksigners) sksigners = sk_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_push(sksigners, signerfile); signerfile = NULL; if (!skkeys) skkeys = sk_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_push(skkeys, keyfile); } keyfile = *++args; } else if (!strcmp(*args, "-keyform")) { if (!args[1]) goto argerr; keyform = str2fmt(*++args); } else if (!strcmp(*args, "-certfile")) { if (!args[1]) goto argerr; certfile = *++args; } else if (!strcmp(*args, "-CAfile")) { if (!args[1]) goto argerr; CAfile = *++args; } else if (!strcmp(*args, "-CApath")) { if (!args[1]) goto argerr; CApath = *++args; } else if (!strcmp(*args, "-in")) { if (!args[1]) goto argerr; infile = *++args; } else if (!strcmp(*args, "-inform")) { if (!args[1]) goto argerr; informat = str2fmt(*++args); } else if (!strcmp(*args, "-outform")) { if (!args[1]) goto argerr; outformat = str2fmt(*++args); } else if (!strcmp(*args, "-out")) { if (!args[1]) goto argerr; outfile = *++args; } else if (!strcmp(*args, "-content")) { if (!args[1]) goto argerr; contfile = *++args; } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) continue; else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) badarg = 1; args++; } if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); goto argerr; } if (operation & SMIME_SIGNERS) { /* Check to see if any final signer needs to be appended */ if (keyfile && !signerfile) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); goto argerr; } if (signerfile) { if (!sksigners) sksigners = sk_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_push(sksigners, signerfile); if (!skkeys) skkeys = sk_OPENSSL_STRING_new_null(); if (!keyfile) keyfile = signerfile; sk_OPENSSL_STRING_push(skkeys, keyfile); } if (!sksigners) { BIO_printf(bio_err, "No signer certificate specified\n"); badarg = 1; } signerfile = NULL; keyfile = NULL; } else if (operation == SMIME_DECRYPT) { if (!recipfile && !keyfile) { BIO_printf(bio_err, "No recipient certificate or key specified\n"); badarg = 1; } } else if (operation == SMIME_ENCRYPT) { if (!*args) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); badarg = 1; } } else if (!operation) badarg = 1; if (badarg) { argerr: BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n"); BIO_printf(bio_err, "where options are\n"); BIO_printf(bio_err, "-encrypt encrypt message\n"); BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); BIO_printf(bio_err, "-sign sign message\n"); BIO_printf(bio_err, "-verify verify signed message\n"); BIO_printf(bio_err, "-pk7out output PKCS#7 structure\n"); #ifndef OPENSSL_NO_DES BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); BIO_printf(bio_err, "-des encrypt with DES\n"); #endif #ifndef OPENSSL_NO_RC2 BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); #endif #ifndef OPENSSL_NO_AES BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); BIO_printf(bio_err, " encrypt PEM output with cbc aes\n"); #endif #ifndef OPENSSL_NO_CAMELLIA BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n"); #endif BIO_printf(bio_err, "-nointern don't search certificates in message for signer\n"); BIO_printf(bio_err, "-nosigs don't verify message signature\n"); BIO_printf(bio_err, "-noverify don't verify signers certificate\n"); BIO_printf(bio_err, "-nocerts don't include signers certificate when signing\n"); BIO_printf(bio_err, "-nodetach use opaque signing\n"); BIO_printf(bio_err, "-noattr don't include any signed attributes\n"); BIO_printf(bio_err, "-binary don't translate message to text\n"); BIO_printf(bio_err, "-certfile file other certificates file\n"); BIO_printf(bio_err, "-signer file signer certificate file\n"); BIO_printf(bio_err, "-recip file recipient certificate file for decryption\n"); BIO_printf(bio_err, "-in file input file\n"); BIO_printf(bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); BIO_printf(bio_err, "-inkey file input private key (if not signer or recipient)\n"); BIO_printf(bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); BIO_printf(bio_err, "-out file output file\n"); BIO_printf(bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); BIO_printf(bio_err, "-content file supply or override content for detached signature\n"); BIO_printf(bio_err, "-to addr to address\n"); BIO_printf(bio_err, "-from ad from address\n"); BIO_printf(bio_err, "-subject s subject\n"); BIO_printf(bio_err, "-text include or delete text MIME headers\n"); BIO_printf(bio_err, "-CApath dir trusted certificates directory\n"); BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); BIO_printf(bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); BIO_printf(bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); BIO_printf(bio_err, "cert.pem recipient certificate(s) for encryption\n"); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } ret = 2; if (!(operation & SMIME_SIGNERS)) flags &= ~PKCS7_DETACHED; if (operation & SMIME_OP) { if (outformat == FORMAT_ASN1) outmode = "wb"; } else { if (flags & PKCS7_BINARY) outmode = "wb"; } if (operation & SMIME_IP) { if (informat == FORMAT_ASN1) inmode = "rb"; } else { if (flags & PKCS7_BINARY) inmode = "rb"; } if (operation == SMIME_ENCRYPT) { if (!cipher) { #ifndef OPENSSL_NO_RC2 cipher = EVP_rc2_40_cbc(); #else BIO_printf(bio_err, "No cipher selected\n"); goto end; #endif } encerts = sk_X509_new_null(); while (*args) { if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, NULL, e, "recipient certificate file"))) { goto end; } sk_X509_push(encerts, cert); cert = NULL; args++; } } if (certfile) { if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, e, "certificate file"))) { ERR_print_errors(bio_err); goto end; } } if (recipfile && (operation == SMIME_DECRYPT)) { if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, e, "recipient certificate file"))) { ERR_print_errors(bio_err); goto end; } } if (operation == SMIME_DECRYPT) { if (!keyfile) keyfile = recipfile; } else if (operation == SMIME_SIGN) { if (!keyfile) keyfile = signerfile; } else keyfile = NULL; if (keyfile) { key = load_key(bio_err, keyfile, keyform, 0, passin, e, "signing key file"); if (!key) goto end; } if (infile) { if (!(in = BIO_new_file(infile, inmode))) { BIO_printf(bio_err, "Can't open input file %s\n", infile); goto end; } } else in = BIO_new_fp(stdin, BIO_NOCLOSE); if (operation & SMIME_IP) { if (informat == FORMAT_SMIME) p7 = SMIME_read_PKCS7(in, &indata); else if (informat == FORMAT_PEM) p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); else if (informat == FORMAT_ASN1) p7 = d2i_PKCS7_bio(in, NULL); else { BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); goto end; } if (!p7) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } if (contfile) { BIO_free(indata); if (!(indata = BIO_new_file(contfile, "rb"))) { BIO_printf(bio_err, "Can't read content file %s\n", contfile); goto end; } } } if (outfile) { if (!(out = BIO_new_file(outfile, outmode))) { BIO_printf(bio_err, "Can't open output file %s\n", outfile); goto end; } } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); } if (operation == SMIME_VERIFY) { if (!(store = setup_verify(bio_err, CAfile, CApath))) goto end; X509_STORE_set_verify_cb(store, smime_cb); if (vpm) X509_STORE_set1_param(store, vpm); } ret = 3; if (operation == SMIME_ENCRYPT) { if (indef) flags |= PKCS7_STREAM; p7 = PKCS7_encrypt(encerts, in, cipher, flags); } else if (operation & SMIME_SIGNERS) { int i; /* * If detached data content we only enable streaming if * S/MIME output format. */ if (operation == SMIME_SIGN) { if (flags & PKCS7_DETACHED) { if (outformat == FORMAT_SMIME) flags |= PKCS7_STREAM; } else if (indef) flags |= PKCS7_STREAM; flags |= PKCS7_PARTIAL; p7 = PKCS7_sign(NULL, NULL, other, in, flags); if (!p7) goto end; } else flags |= PKCS7_REUSE_DIGEST; for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, e, "signer certificate"); if (!signer) goto end; key = load_key(bio_err, keyfile, keyform, 0, passin, e, "signing key file"); if (!key) goto end; if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) goto end; X509_free(signer); signer = NULL; EVP_PKEY_free(key); key = NULL; } /* If not streaming or resigning finalize structure */ if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { if (!PKCS7_final(p7, in, flags)) goto end; } } if (!p7) { BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); goto end; } ret = 4; if (operation == SMIME_DECRYPT) { if (!PKCS7_decrypt(p7, key, recip, out, flags)) { BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); goto end; } } else if (operation == SMIME_VERIFY) { STACK_OF(X509) * signers; if (PKCS7_verify(p7, other, store, indata, out, flags)) BIO_printf(bio_err, "Verification successful\n"); else { BIO_printf(bio_err, "Verification failure\n"); goto end; } signers = PKCS7_get0_signers(p7, other, flags); if (!save_certs(signerfile, signers)) { BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); ret = 5; goto end; } sk_X509_free(signers); } else if (operation == SMIME_PK7OUT) PEM_write_bio_PKCS7(out, p7); else { if (to) BIO_printf(out, "To: %s\n", to); if (from) BIO_printf(out, "From: %s\n", from); if (subject) BIO_printf(out, "Subject: %s\n", subject); if (outformat == FORMAT_SMIME) { if (operation == SMIME_RESIGN) SMIME_write_PKCS7(out, p7, indata, flags); else SMIME_write_PKCS7(out, p7, in, flags); } else if (outformat == FORMAT_PEM) PEM_write_bio_PKCS7_stream(out, p7, in, flags); else if (outformat == FORMAT_ASN1) i2d_PKCS7_bio_stream(out, p7, in, flags); else { BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); goto end; } } ret = 0; end: if (ret) ERR_print_errors(bio_err); sk_X509_pop_free(encerts, X509_free); sk_X509_pop_free(other, X509_free); if (vpm) X509_VERIFY_PARAM_free(vpm); if (sksigners) sk_OPENSSL_STRING_free(sksigners); if (skkeys) sk_OPENSSL_STRING_free(skkeys); X509_STORE_free(store); X509_free(cert); X509_free(recip); X509_free(signer); EVP_PKEY_free(key); PKCS7_free(p7); BIO_free(in); BIO_free(indata); BIO_free_all(out); free(passin); return (ret); }
int main(int argc, char **argv) { BIO *bio_in, *bio_content, *bio_out, *bio_cert, *bio_pkey; STACK_OF(X509) *certs; const EVP_CIPHER *cipher; EVP_PKEY *pkey; X509_STORE *store; X509 *cert; PKCS7 *p7; size_t len; char *out; int flags; ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); /* * A bunch of setup... */ cipher = EVP_aes_256_cbc(); if (cipher == NULL) fatal("cipher"); certs = sk_X509_new_null(); if (certs == NULL) fatal("sk_X509_new_null"); bio_cert = BIO_new_mem_buf((char *)certificate, sizeof(certificate)); if (bio_cert == NULL) fatal("BIO_new_mem_buf certificate"); cert = PEM_read_bio_X509_AUX(bio_cert, NULL, NULL, NULL); if (cert == NULL) fatal("PEM_read_bio_X509_AUX"); sk_X509_push(certs, cert); store = X509_STORE_new(); if (store == NULL) fatal("X509_STORE_new"); X509_STORE_set_verify_cb(store, x509_store_callback); bio_pkey = BIO_new_mem_buf((char *)private_key, sizeof(private_key)); if (bio_pkey == NULL) fatal("BIO_new_mem_buf private_key"); pkey = PEM_read_bio_PrivateKey(bio_pkey, NULL, NULL, NULL); if (pkey == NULL) fatal("PEM_read_bio_PrivateKey"); bio_content = BIO_new_mem_buf((char *)message, sizeof(message)); if (bio_content == NULL) fatal("BIO_new_mem_buf message"); /* * Encrypt and then decrypt. */ if (BIO_reset(bio_content) != 1) fatal("BIO_reset"); bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) fatal("BIO_new"); p7 = PKCS7_encrypt(certs, bio_content, cipher, 0); if (p7 == NULL) fatal("PKCS7_encrypt"); if (PEM_write_bio_PKCS7(bio_out, p7) != 1) fatal("PEM_write_bio_PKCS7"); PKCS7_free(p7); bio_in = bio_out; bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) fatal("BIO_new"); p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); if (p7 == NULL) fatal("PEM_read_bio_PKCS7"); if (PKCS7_decrypt(p7, pkey, cert, bio_out, 0) != 1) fatal("PKCS7_decrypt"); len = BIO_get_mem_data(bio_out, &out); message_compare(out, len); BIO_free(bio_out); /* * Sign and then verify. */ if (BIO_reset(bio_content) != 1) fatal("BIO_reset"); bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) fatal("BIO_new"); p7 = PKCS7_sign(cert, pkey, certs, bio_content, 0); if (p7 == NULL) fatal("PKCS7_sign"); if (PEM_write_bio_PKCS7(bio_out, p7) != 1) fatal("PEM_write_bio_PKCS7"); PKCS7_free(p7); bio_in = bio_out; bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) fatal("BIO_new"); p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); if (p7 == NULL) fatal("PEM_read_bio_PKCS7"); if (PKCS7_verify(p7, certs, store, NULL, bio_out, 0) != 1) fatal("PKCS7_verify"); len = BIO_get_mem_data(bio_out, &out); message_compare(out, len); BIO_free(bio_in); BIO_free(bio_out); /* * Sign and then verify with a detached signature. */ if (BIO_reset(bio_content) != 1) fatal("BIO_reset"); bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) fatal("BIO_new"); flags = PKCS7_DETACHED|PKCS7_PARTIAL; p7 = PKCS7_sign(NULL, NULL, NULL, bio_content, flags); if (p7 == NULL) fatal("PKCS7_sign"); if (PKCS7_sign_add_signer(p7, cert, pkey, NULL, flags) == NULL) fatal("PKCS7_sign_add_signer"); if (PKCS7_final(p7, bio_content, flags) != 1) fatal("PKCS7_final"); if (PEM_write_bio_PKCS7(bio_out, p7) != 1) fatal("PEM_write_bio_PKCS7"); PKCS7_free(p7); /* bio_out contains only the detached signature. */ bio_in = bio_out; if (BIO_reset(bio_content) != 1) fatal("BIO_reset"); bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) fatal("BIO_new"); p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); if (p7 == NULL) fatal("PEM_read_bio_PKCS7"); if (PKCS7_verify(p7, certs, store, bio_content, bio_out, flags) != 1) fatal("PKCS7_verify"); len = BIO_get_mem_data(bio_out, &out); message_compare(out, len); BIO_free(bio_in); BIO_free(bio_out); BIO_free(bio_content); return 0; }
/* * Unwrap PKCS#7 data and decrypt if necessary */ int pkcs7_unwrap(struct scep *s) { BIO *memorybio; BIO *outbio; BIO *pkcs7bio; int i, len, bytes, used; STACK_OF(PKCS7_SIGNER_INFO) *sk; PKCS7 *p7enc; PKCS7_SIGNER_INFO *si; STACK_OF(X509_ATTRIBUTE) *attribs; char *p; unsigned char buffer[1024]; X509 *recipientcert; EVP_PKEY *recipientkey; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if (v_flag) printf("%s: reading outer PKCS#7\n",pname); if ((len = BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0) { fprintf(stderr, "%s: error reading PKCS#7 data\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: PKCS#7 payload size: %d bytes\n", pname, len); BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL); if (d_flag) { printf("%s: printing PEM fomatted PKCS#7\n", pname); PEM_write_PKCS7(stdout, s->reply_p7); } /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { fprintf(stderr, "%s: PKCS#7 is not signed!\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL); if (pkcs7bio == NULL) { fprintf(stderr, "%s: cannot get PKCS#7 data\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Copy enveloped data from PKCS#7 */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } BIO_flush(outbio); if (v_flag) printf("%s: PKCS#7 contains %d bytes of enveloped data\n", pname, used); /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL) { fprintf(stderr, "%s: cannot get signer info!\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Verify signature */ if (v_flag) printf("%s: verifying signature\n", pname); si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cacert) <= 0) { fprintf(stderr, "%s: error verifying signature\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: signature ok\n", pname); /* Get signed attributes */ if (v_flag) printf("%s: finding signed attributes\n", pname); attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL) { fprintf(stderr, "%s: no attributes found\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Transaction id */ if ((get_signed_attribute(attribs, nid_transId, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find transId\n", pname); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: reply transaction id: %s\n", pname, p); if (strncmp(s->transaction_id, p, strlen(p))) { fprintf(stderr, "%s: transaction id mismatch\n", pname); exit (SCEP_PKISTATUS_P7); } /* Message type, should be of type CertRep */ if ((i = get_signed_attribute(attribs, nid_messageType, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find messageType\n", pname); exit (SCEP_PKISTATUS_P7); } if (atoi(p) != 3) { fprintf(stderr, "%s: wrong message type in reply\n", pname); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: reply message type is good\n", pname); /* Sender and recipient nonces: */ if ((i = get_signed_attribute(attribs, nid_senderNonce, V_ASN1_OCTET_STRING, &p)) == 1) { if (v_flag) fprintf(stderr, "%s: cannot find senderNonce\n", pname); /* Some implementations don't put in on reply */ /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX exit (SCEP_PKISTATUS_P7); */ } s->reply_sender_nonce = p; if (v_flag) { printf("%s: senderNonce in reply: ", pname); for (i = 0; i < 16; i++) { printf("%02X", s->reply_sender_nonce[i]); } printf("\n"); } if (( i = get_signed_attribute(attribs, nid_recipientNonce, V_ASN1_OCTET_STRING, &p)) == 1) { fprintf(stderr, "%s: cannot find recipientNonce\n", pname); exit (SCEP_PKISTATUS_P7); } s->reply_recipient_nonce = p; if (v_flag) { printf("%s: recipientNonce in reply: ", pname); for (i = 0; i < 16; i++) { printf("%02X", s->reply_recipient_nonce[i]); } printf("\n"); } /* * Compare recipient nonce to original sender nonce * The draft says nothing about this, but it makes sense to me.. * XXXXXXXXXXXXXX check */ for (i = 0; i < 16; i++) { if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) { if (v_flag) fprintf(stderr, "%s: corrupted nonce " "received\n", pname); /* Instead of exit, break out */ break; } } /* Get pkiStatus */ if ((i = get_signed_attribute(attribs, nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find pkiStatus\n", pname); /* This is a mandatory attribute.. */ exit (SCEP_PKISTATUS_P7); } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: printf("%s: pkistatus: SUCCESS\n",pname); s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: printf("%s: pkistatus: FAILURE\n",pname); s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: printf("%s: pkistatus: PENDING\n",pname); s->pki_status = SCEP_PKISTATUS_PENDING; break; default: fprintf(stderr, "%s: wrong pkistatus in reply\n",pname); exit (SCEP_PKISTATUS_P7); } /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if ((i = get_signed_attribute(attribs, nid_failInfo, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find failInfo\n", pname); exit (SCEP_PKISTATUS_P7); } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADALG_STR); break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADMSGCHK_STR); break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADREQ_STR); break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADTIME_STR); break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADCERTID_STR); break; default: fprintf(stderr, "%s: wrong failInfo in " "reply\n",pname); exit (SCEP_PKISTATUS_P7); } } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ if (v_flag && (used != 0)) { fprintf(stderr, "%s: illegal size of payload\n", pname); } return (0); } /* We got success and expect data */ if (used == 0) { fprintf(stderr, "%s: illegal size of payload\n", pname); exit (SCEP_PKISTATUS_P7); } /* Decrypt the inner PKCS#7 */ if ((s->request_type == SCEP_REQUEST_PKCSREQ) || (s->request_type == SCEP_REQUEST_GETCERTINIT)) { recipientcert = s->signercert; recipientkey = s->signerkey; } else { recipientcert = localcert; recipientkey = rsa; } if (v_flag) printf("%s: reading inner PKCS#7\n",pname); p7enc = d2i_PKCS7_bio(outbio, NULL); if (p7enc == NULL) { fprintf(stderr, "%s: cannot read inner PKCS#7\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } if (d_flag) { printf("%s: printing PEM fomatted PKCS#7\n", pname); PEM_write_PKCS7(stdout, p7enc); } /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (v_flag) printf("%s: decrypting inner PKCS#7\n",pname); if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { fprintf(stderr, "%s: error decrypting inner PKCS#7\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } BIO_flush(outbio); /* Write decrypted data */ s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload); if (v_flag) printf("%s: PKCS#7 payload size: %d bytes\n", pname, s->reply_len); BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL); return (0); }
int cve_1790app(char *filename) { int encrypt,flags_nm=0,out_size=0; PKCS7 *pkcs7; const EVP_CIPHER *cipher; X509 *cert; EVP_PKEY *pkey; FILE *fp; BIO *pkcs7_bio,*out,*in_fileBIO; int i=0; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); if (!(out = BIO_new_fp(stdout, BIO_NOCLOSE))) { fprintf(stderr, "Error creating output BIO objects\n"); goto err; } // read from file and Decrypt { if (!(fp = fopen(RSA_SERVER_KEY, "r")) ||!(pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))) { printf("Error reading private key in %s\n",RSA_SERVER_KEY); goto err; } fclose(fp); if (!(fp = fopen(RSA_SERVER_CERT, "r")) ||!(cert = PEM_read_X509(fp, NULL, NULL, NULL))) { printf( "Error reading decryption certificate in %s\n", RSA_SERVER_CERT); goto err; } fclose(fp); //create a file BIO for input file in_fileBIO = BIO_new_file(filename,"r"); if( in_fileBIO == NULL){ printf("Error in creating bio file\n"); goto err; } if (!(pkcs7 = SMIME_read_PKCS7(in_fileBIO, &pkcs7_bio))) { printf("\nError reading PKCS#7 object\n"); goto err; } printf("Invoking PKCS7_decrypt function..\n"); if (PKCS7_decrypt(pkcs7, pkey, cert, out, flags_nm) != 1) { printf("Error decrypting PKCS#7 object\n"); goto err; } } BIO_free(in_fileBIO); return 0; err: return -1; }
unsigned char *SCEP_MSG_decrypt( SCEP_MSG *msg, EVP_PKEY *ppkey, X509 *cert, long *len ) { char *ret = NULL; char *data = NULL; BIO *bio = NULL; BIO *bio_err = NULL; BIO *bio_dup = NULL; X509 *foo_cert = NULL; EVP_PKEY *pkey = NULL; SCEP_RECIP_INFO *rinfo; if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); /* Get the recipient information to build the fake * certificate needed into the PKCS7_decrypt function */ rinfo = &(msg->env_data.recip_info); /* We need a private key */ if( ppkey ) pkey = ppkey; else pkey = msg->signer_pkey; if( !pkey ) return (NULL); if( cert ) { foo_cert = cert; } else { if( (foo_cert = X509_new()) == NULL ) { BIO_printf(bio_err, "%s:%d: foo_cert not alloc\n", __FILE__, __LINE__); goto err; }; X509_set_issuer_name(foo_cert,rinfo->ias->issuer); X509_set_subject_name(foo_cert,rinfo->ias->issuer); X509_set_serialNumber(foo_cert,rinfo->ias->serial); X509_set_pubkey(foo_cert, pkey); } bio = BIO_new(BIO_s_mem()); if (PKCS7_decrypt( msg->env_data.p7env, pkey, foo_cert, bio, 0) == 0) { // printf("%s:%d: decryption failed\n", __FILE__, // __LINE__); goto err; } BIO_flush(bio); if( len ) *len = BIO_get_mem_data(bio, &data); switch ( msg->messageType ) { case MSG_CERTREP: if( msg->env_data.crl = d2i_X509_CRL_bio(bio,NULL) ) { /* There is a CRL */ ret = (char *) msg->env_data.crl; } // p7 = d2i_PKCS7_bio(bio, NULL); break; case MSG_PKCSREQ: msg->env_data.content.req = d2i_X509_REQ_bio(bio, NULL); ret = (char *) msg->env_data.content.req; break; case MSG_GETCERTINITIAL: // req->rd.is = d2i_issuer_and_subject_bio(bio, NULL); break; case MSG_GETCERT: case MSG_GETCRL: msg->env_data.content.ias = d2i_PKCS7_ias_bio(NULL, bio); ret = (char *) msg->env_data.content.ias; break; case MSG_V2PROXY: // unsupported case MSG_V2REQUEST: // unsupported default: // BIO_printf(bio_err, "%s:%d: unknown message type: %s\n", // __FILE__, __LINE__, msg->messageType); break; } err: if( foo_cert && !cert ) X509_free( foo_cert ); if( bio ) BIO_free(bio); ERR_clear_error(); return ret; }