pk7_smime.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:12k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* pk7_smime.c */
  2. /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
  3.  * project.
  4.  */
  5. /* ====================================================================
  6.  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  *
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer. 
  14.  *
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in
  17.  *    the documentation and/or other materials provided with the
  18.  *    distribution.
  19.  *
  20.  * 3. All advertising materials mentioning features or use of this
  21.  *    software must display the following acknowledgment:
  22.  *    "This product includes software developed by the OpenSSL Project
  23.  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24.  *
  25.  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26.  *    endorse or promote products derived from this software without
  27.  *    prior written permission. For written permission, please contact
  28.  *    licensing@OpenSSL.org.
  29.  *
  30.  * 5. Products derived from this software may not be called "OpenSSL"
  31.  *    nor may "OpenSSL" appear in their names without prior written
  32.  *    permission of the OpenSSL Project.
  33.  *
  34.  * 6. Redistributions of any form whatsoever must retain the following
  35.  *    acknowledgment:
  36.  *    "This product includes software developed by the OpenSSL Project
  37.  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38.  *
  39.  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  51.  * ====================================================================
  52.  *
  53.  * This product includes cryptographic software written by Eric Young
  54.  * (eay@cryptsoft.com).  This product includes software written by Tim
  55.  * Hudson (tjh@cryptsoft.com).
  56.  *
  57.  */
  58. /* Simple PKCS#7 processing functions */
  59. #include <stdio.h>
  60. #include "cryptlib.h"
  61. #include <openssl/x509.h>
  62. #include <openssl/x509v3.h>
  63. PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
  64.   BIO *data, int flags)
  65. {
  66. PKCS7 *p7;
  67. PKCS7_SIGNER_INFO *si;
  68. BIO *p7bio;
  69. STACK_OF(X509_ALGOR) *smcap;
  70. int i;
  71. if(!X509_check_private_key(signcert, pkey)) {
  72. PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
  73.                 return NULL;
  74. }
  75. if(!(p7 = PKCS7_new())) {
  76. PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
  77. return NULL;
  78. }
  79. PKCS7_set_type(p7, NID_pkcs7_signed);
  80. PKCS7_content_new(p7, NID_pkcs7_data);
  81.      if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) {
  82. PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
  83. PKCS7_free(p7);
  84. return NULL;
  85. }
  86. if(!(flags & PKCS7_NOCERTS)) {
  87. PKCS7_add_certificate(p7, signcert);
  88. if(certs) for(i = 0; i < sk_X509_num(certs); i++)
  89. PKCS7_add_certificate(p7, sk_X509_value(certs, i));
  90. }
  91. if(!(flags & PKCS7_NOATTR)) {
  92. PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
  93. V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
  94. /* Add SMIMECapabilities */
  95. if(!(flags & PKCS7_NOSMIMECAP))
  96. {
  97. if(!(smcap = sk_X509_ALGOR_new_null())) {
  98. PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
  99. PKCS7_free(p7);
  100. return NULL;
  101. }
  102. #ifndef OPENSSL_NO_DES
  103. PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1);
  104. #endif
  105. #ifndef OPENSSL_NO_RC2
  106. PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128);
  107. PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64);
  108. #endif
  109. #ifndef OPENSSL_NO_DES
  110. PKCS7_simple_smimecap (smcap, NID_des_cbc, -1);
  111. #endif
  112. #ifndef OPENSSL_NO_RC2
  113. PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40);
  114. #endif
  115. PKCS7_add_attrib_smimecap (si, smcap);
  116. sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
  117. }
  118. }
  119. if (flags & PKCS7_STREAM)
  120. return p7;
  121. if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
  122. PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
  123. PKCS7_free(p7);
  124. return NULL;
  125. }
  126. SMIME_crlf_copy(data, p7bio, flags);
  127. if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
  128.         if (!PKCS7_dataFinal(p7,p7bio)) {
  129. PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN);
  130. PKCS7_free(p7);
  131. BIO_free_all(p7bio);
  132. return NULL;
  133. }
  134. BIO_free_all(p7bio);
  135. return p7;
  136. }
  137. int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
  138. BIO *indata, BIO *out, int flags)
  139. {
  140. STACK_OF(X509) *signers;
  141. X509 *signer;
  142. STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
  143. PKCS7_SIGNER_INFO *si;
  144. X509_STORE_CTX cert_ctx;
  145. char buf[4096];
  146. int i, j=0, k, ret = 0;
  147. BIO *p7bio;
  148. BIO *tmpin, *tmpout;
  149. if(!p7) {
  150. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
  151. return 0;
  152. }
  153. if(!PKCS7_type_is_signed(p7)) {
  154. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
  155. return 0;
  156. }
  157. /* Check for no data and no content: no data to verify signature */
  158. if(PKCS7_get_detached(p7) && !indata) {
  159. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
  160. return 0;
  161. }
  162. #if 0
  163. /* NB: this test commented out because some versions of Netscape
  164.  * illegally include zero length content when signing data.
  165.  */
  166. /* Check for data and content: two sets of data */
  167. if(!PKCS7_get_detached(p7) && indata) {
  168. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CONTENT_AND_DATA_PRESENT);
  169. return 0;
  170. }
  171. #endif
  172. sinfos = PKCS7_get_signer_info(p7);
  173. if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
  174. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
  175. return 0;
  176. }
  177. signers = PKCS7_get0_signers(p7, certs, flags);
  178. if(!signers) return 0;
  179. /* Now verify the certificates */
  180. if (!(flags & PKCS7_NOVERIFY)) for (k = 0; k < sk_X509_num(signers); k++) {
  181. signer = sk_X509_value (signers, k);
  182. if (!(flags & PKCS7_NOCHAIN)) {
  183. if(!X509_STORE_CTX_init(&cert_ctx, store, signer,
  184. p7->d.sign->cert))
  185. {
  186. PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB);
  187. sk_X509_free(signers);
  188. return 0;
  189. }
  190. X509_STORE_CTX_set_purpose(&cert_ctx,
  191. X509_PURPOSE_SMIME_SIGN);
  192. } else if(!X509_STORE_CTX_init (&cert_ctx, store, signer, NULL)) {
  193. PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB);
  194. sk_X509_free(signers);
  195. return 0;
  196. }
  197. if (!(flags & PKCS7_NOCRL))
  198. X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl);
  199. i = X509_verify_cert(&cert_ctx);
  200. if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx);
  201. X509_STORE_CTX_cleanup(&cert_ctx);
  202. if (i <= 0) {
  203. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CERTIFICATE_VERIFY_ERROR);
  204. ERR_add_error_data(2, "Verify error:",
  205.  X509_verify_cert_error_string(j));
  206. sk_X509_free(signers);
  207. return 0;
  208. }
  209. /* Check for revocation status here */
  210. }
  211. /* Performance optimization: if the content is a memory BIO then
  212.  * store its contents in a temporary read only memory BIO. This
  213.  * avoids potentially large numbers of slow copies of data which will
  214.  * occur when reading from a read write memory BIO when signatures
  215.  * are calculated.
  216.  */
  217. if (indata && (BIO_method_type(indata) == BIO_TYPE_MEM))
  218. {
  219. char *ptr;
  220. long len;
  221. len = BIO_get_mem_data(indata, &ptr);
  222. tmpin = BIO_new_mem_buf(ptr, len);
  223. if (tmpin == NULL)
  224. {
  225. PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
  226. return 0;
  227. }
  228. }
  229. else
  230. tmpin = indata;
  231. p7bio=PKCS7_dataInit(p7,tmpin);
  232. if(flags & PKCS7_TEXT) {
  233. if(!(tmpout = BIO_new(BIO_s_mem()))) {
  234. PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
  235. goto err;
  236. }
  237. } else tmpout = out;
  238. /* We now have to 'read' from p7bio to calculate digests etc. */
  239. for (;;)
  240. {
  241. i=BIO_read(p7bio,buf,sizeof(buf));
  242. if (i <= 0) break;
  243. if (tmpout) BIO_write(tmpout, buf, i);
  244. }
  245. if(flags & PKCS7_TEXT) {
  246. if(!SMIME_text(tmpout, out)) {
  247. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SMIME_TEXT_ERROR);
  248. BIO_free(tmpout);
  249. goto err;
  250. }
  251. BIO_free(tmpout);
  252. }
  253. /* Now Verify All Signatures */
  254. if (!(flags & PKCS7_NOSIGS))
  255.     for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
  256. {
  257. si=sk_PKCS7_SIGNER_INFO_value(sinfos,i);
  258. signer = sk_X509_value (signers, i);
  259. j=PKCS7_signatureVerify(p7bio,p7,si, signer);
  260. if (j <= 0) {
  261. PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SIGNATURE_FAILURE);
  262. goto err;
  263. }
  264. }
  265. ret = 1;
  266. err:
  267. if (tmpin == indata)
  268. {
  269. if (indata) BIO_pop(p7bio);
  270. }
  271. BIO_free_all(p7bio);
  272. sk_X509_free(signers);
  273. return ret;
  274. }
  275. STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
  276. {
  277. STACK_OF(X509) *signers;
  278. STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
  279. PKCS7_SIGNER_INFO *si;
  280. PKCS7_ISSUER_AND_SERIAL *ias;
  281. X509 *signer;
  282. int i;
  283. if(!p7) {
  284. PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_INVALID_NULL_POINTER);
  285. return NULL;
  286. }
  287. if(!PKCS7_type_is_signed(p7)) {
  288. PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
  289. return NULL;
  290. }
  291. /* Collect all the signers together */
  292. sinfos = PKCS7_get_signer_info(p7);
  293. if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
  294. PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS);
  295. return 0;
  296. }
  297. if(!(signers = sk_X509_new_null())) {
  298. PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,ERR_R_MALLOC_FAILURE);
  299. return NULL;
  300. }
  301. for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
  302. {
  303.     si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
  304.     ias = si->issuer_and_serial;
  305.     signer = NULL;
  306. /* If any certificates passed they take priority */
  307.     if (certs) signer = X509_find_by_issuer_and_serial (certs,
  308.   ias->issuer, ias->serial);
  309.     if (!signer && !(flags & PKCS7_NOINTERN)
  310. && p7->d.sign->cert) signer =
  311.               X509_find_by_issuer_and_serial (p7->d.sign->cert,
  312.        ias->issuer, ias->serial);
  313.     if (!signer) {
  314. PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
  315. sk_X509_free(signers);
  316. return 0;
  317.     }
  318.     sk_X509_push(signers, signer);
  319. }
  320. return signers;
  321. }
  322. /* Build a complete PKCS#7 enveloped data */
  323. PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
  324. int flags)
  325. {
  326. PKCS7 *p7;
  327. BIO *p7bio = NULL;
  328. int i;
  329. X509 *x509;
  330. if(!(p7 = PKCS7_new())) {
  331. PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
  332. return NULL;
  333. }
  334. PKCS7_set_type(p7, NID_pkcs7_enveloped);
  335. if(!PKCS7_set_cipher(p7, cipher)) {
  336. PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER);
  337. goto err;
  338. }
  339. for(i = 0; i < sk_X509_num(certs); i++) {
  340. x509 = sk_X509_value(certs, i);
  341. if(!PKCS7_add_recipient(p7, x509)) {
  342. PKCS7err(PKCS7_F_PKCS7_ENCRYPT,
  343. PKCS7_R_ERROR_ADDING_RECIPIENT);
  344. goto err;
  345. }
  346. }
  347. if(!(p7bio = PKCS7_dataInit(p7, NULL))) {
  348. PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
  349. goto err;
  350. }
  351. SMIME_crlf_copy(in, p7bio, flags);
  352. BIO_flush(p7bio);
  353.         if (!PKCS7_dataFinal(p7,p7bio)) {
  354. PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR);
  355. goto err;
  356. }
  357.         BIO_free_all(p7bio);
  358. return p7;
  359. err:
  360. BIO_free(p7bio);
  361. PKCS7_free(p7);
  362. return NULL;
  363. }
  364. int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
  365. {
  366. BIO *tmpmem;
  367. int ret, i;
  368. char buf[4096];
  369. if(!p7) {
  370. PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER);
  371. return 0;
  372. }
  373. if(!PKCS7_type_is_enveloped(p7)) {
  374. PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE);
  375. return 0;
  376. }
  377. if(cert && !X509_check_private_key(cert, pkey)) {
  378. PKCS7err(PKCS7_F_PKCS7_DECRYPT,
  379. PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
  380. return 0;
  381. }
  382. if(!(tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert))) {
  383. PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR);
  384. return 0;
  385. }
  386. if (flags & PKCS7_TEXT) {
  387. BIO *tmpbuf, *bread;
  388. /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
  389. if(!(tmpbuf = BIO_new(BIO_f_buffer()))) {
  390. PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
  391. return 0;
  392. }
  393. if(!(bread = BIO_push(tmpbuf, tmpmem))) {
  394. PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
  395. return 0;
  396. }
  397. ret = SMIME_text(bread, data);
  398. BIO_free_all(bread);
  399. return ret;
  400. } else {
  401. for(;;) {
  402. i = BIO_read(tmpmem, buf, sizeof(buf));
  403. if(i <= 0) break;
  404. BIO_write(data, buf, i);
  405. }
  406. BIO_free_all(tmpmem);
  407. return 1;
  408. }
  409. }