Signed receipt generation code.
This commit is contained in:
parent
eb9d8d8cd4
commit
36309aa2be
6 changed files with 188 additions and 2 deletions
32
apps/cms.c
32
apps/cms.c
|
@ -91,7 +91,7 @@ static CMS_ReceiptRequest *make_receipt_request(STACK *rr_to, int rr_allorfirst,
|
|||
#define SMIME_COMPRESS (12 | SMIME_OP)
|
||||
#define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
|
||||
#define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
|
||||
#define SMIME_SIGN_RECEIPT (15 | SMIME_OP | SMIME_IP)
|
||||
#define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP)
|
||||
#define SMIME_VERIFY_RECEIPT (16 | SMIME_IP)
|
||||
|
||||
int MAIN(int, char **);
|
||||
|
@ -159,6 +159,8 @@ int MAIN(int argc, char **argv)
|
|||
operation = SMIME_DECRYPT;
|
||||
else if (!strcmp (*args, "-sign"))
|
||||
operation = SMIME_SIGN;
|
||||
else if (!strcmp (*args, "-sign_receipt"))
|
||||
operation = SMIME_SIGN_RECEIPT;
|
||||
else if (!strcmp (*args, "-resign"))
|
||||
operation = SMIME_RESIGN;
|
||||
else if (!strcmp (*args, "-verify"))
|
||||
|
@ -541,6 +543,7 @@ int MAIN(int argc, char **argv)
|
|||
keyfile = NULL;
|
||||
need_rand = 1;
|
||||
}
|
||||
|
||||
else if (operation == SMIME_DECRYPT)
|
||||
{
|
||||
if (!recipfile && !keyfile && !secret_key)
|
||||
|
@ -724,12 +727,22 @@ int MAIN(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
if (operation == SMIME_SIGN_RECEIPT)
|
||||
{
|
||||
if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM,NULL,
|
||||
e, "receipt signer certificate file")))
|
||||
{
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation == SMIME_DECRYPT)
|
||||
{
|
||||
if (!keyfile)
|
||||
keyfile = recipfile;
|
||||
}
|
||||
else if (operation == SMIME_SIGN)
|
||||
else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT))
|
||||
{
|
||||
if (!keyfile)
|
||||
keyfile = signerfile;
|
||||
|
@ -888,6 +901,21 @@ int MAIN(int argc, char **argv)
|
|||
secret_key, secret_keylen,
|
||||
flags);
|
||||
|
||||
}
|
||||
else if (operation == SMIME_SIGN_RECEIPT)
|
||||
{
|
||||
CMS_ContentInfo *srcms = NULL;
|
||||
STACK_OF(CMS_SignerInfo) *sis;
|
||||
CMS_SignerInfo *si;
|
||||
sis = CMS_get0_SignerInfos(cms);
|
||||
if (!sis)
|
||||
goto end;
|
||||
si = sk_CMS_SignerInfo_value(sis, 0);
|
||||
srcms = CMS_sign_receipt(si, signer, key, other, flags);
|
||||
if (!srcms)
|
||||
goto end;
|
||||
CMS_ContentInfo_free(cms);
|
||||
cms = srcms;
|
||||
}
|
||||
else if (operation & SMIME_SIGNERS)
|
||||
{
|
||||
|
|
|
@ -140,6 +140,11 @@ int CMS_final(CMS_ContentInfo *cms, BIO *data, int flags);
|
|||
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
|
||||
BIO *data, unsigned int flags);
|
||||
|
||||
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
|
||||
X509 *signcert, EVP_PKEY *pkey,
|
||||
STACK_OF(X509) *certs,
|
||||
unsigned int flags);
|
||||
|
||||
int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
|
||||
CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
|
||||
|
||||
|
@ -342,6 +347,7 @@ void ERR_load_CMS_strings(void);
|
|||
#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116
|
||||
#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117
|
||||
#define CMS_F_CMS_DIGEST_VERIFY 118
|
||||
#define CMS_F_CMS_ENCODE_RECEIPT 161
|
||||
#define CMS_F_CMS_ENCRYPT 119
|
||||
#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120
|
||||
#define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121
|
||||
|
@ -357,6 +363,7 @@ void ERR_load_CMS_strings(void);
|
|||
#define CMS_F_CMS_GET0_ENVELOPED 131
|
||||
#define CMS_F_CMS_GET0_REVOCATION_CHOICES 132
|
||||
#define CMS_F_CMS_GET0_SIGNED 133
|
||||
#define CMS_F_CMS_MSGSIGDIGEST_ADD1 162
|
||||
#define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159
|
||||
#define CMS_F_CMS_RECEIPT_VERIFY 160
|
||||
#define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134
|
||||
|
@ -380,6 +387,7 @@ void ERR_load_CMS_strings(void);
|
|||
#define CMS_F_CMS_SIGNERINFO_VERIFY 152
|
||||
#define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153
|
||||
#define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154
|
||||
#define CMS_F_CMS_SIGN_RECEIPT 163
|
||||
#define CMS_F_CMS_STREAM 155
|
||||
#define CMS_F_CMS_UNCOMPRESS 156
|
||||
#define CMS_F_CMS_VERIFY 157
|
||||
|
@ -427,6 +435,7 @@ void ERR_load_CMS_strings(void);
|
|||
#define CMS_R_NO_DEFAULT_DIGEST 128
|
||||
#define CMS_R_NO_DIGEST_SET 129
|
||||
#define CMS_R_NO_KEY 130
|
||||
#define CMS_R_NO_KEY_OR_CERT 174
|
||||
#define CMS_R_NO_MATCHING_DIGEST 131
|
||||
#define CMS_R_NO_MATCHING_RECIPIENT 132
|
||||
#define CMS_R_NO_MATCHING_SIGNATURE 166
|
||||
|
|
|
@ -91,6 +91,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
|
|||
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "CMS_DIGESTALGORITHM_INIT_BIO"},
|
||||
{ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL), "CMS_DIGESTEDDATA_DO_FINAL"},
|
||||
{ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY), "CMS_digest_verify"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCODE_RECEIPT), "CMS_ENCODE_RECEIPT"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPT), "CMS_encrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO), "CMS_ENCRYPTEDCONTENT_INIT_BIO"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT), "CMS_EncryptedData_decrypt"},
|
||||
|
@ -106,6 +107,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
|
|||
{ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "CMS_GET0_ENVELOPED"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES), "CMS_GET0_REVOCATION_CHOICES"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"},
|
||||
{ERR_FUNC(CMS_F_CMS_MSGSIGDIGEST_ADD1), "CMS_MSGSIGDIGEST_ADD1"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECEIPTREQUEST_CREATE0), "CMS_ReceiptRequest_create0"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECEIPT_VERIFY), "CMS_RECEIPT_VERIFY"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT), "CMS_RecipientInfo_decrypt"},
|
||||
|
@ -129,6 +131,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
|
|||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY), "CMS_SignerInfo_verify"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CERT), "CMS_SIGNERINFO_VERIFY_CERT"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT), "CMS_SignerInfo_verify_content"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGN_RECEIPT), "CMS_SIGN_RECEIPT"},
|
||||
{ERR_FUNC(CMS_F_CMS_STREAM), "CMS_stream"},
|
||||
{ERR_FUNC(CMS_F_CMS_UNCOMPRESS), "CMS_uncompress"},
|
||||
{ERR_FUNC(CMS_F_CMS_VERIFY), "CMS_verify"},
|
||||
|
@ -179,6 +182,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
|
|||
{ERR_REASON(CMS_R_NO_DEFAULT_DIGEST) ,"no default digest"},
|
||||
{ERR_REASON(CMS_R_NO_DIGEST_SET) ,"no digest set"},
|
||||
{ERR_REASON(CMS_R_NO_KEY) ,"no key"},
|
||||
{ERR_REASON(CMS_R_NO_KEY_OR_CERT) ,"no key or cert"},
|
||||
{ERR_REASON(CMS_R_NO_MATCHING_DIGEST) ,"no matching digest"},
|
||||
{ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"},
|
||||
{ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE) ,"no matching signature"},
|
||||
|
|
|
@ -190,6 +190,8 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
|
|||
*prto = rr->receiptsTo;
|
||||
}
|
||||
|
||||
/* Digest a SignerInfo structure for msgSigDigest attribute processing */
|
||||
|
||||
static int cms_msgSigDigest(CMS_SignerInfo *si,
|
||||
unsigned char *dig, unsigned int *diglen)
|
||||
{
|
||||
|
@ -203,6 +205,26 @@ static int cms_msgSigDigest(CMS_SignerInfo *si,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Add a msgSigDigest attribute to a SignerInfo */
|
||||
|
||||
int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
|
||||
{
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
unsigned int diglen;
|
||||
if (!cms_msgSigDigest(src, dig, &diglen))
|
||||
{
|
||||
CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest,
|
||||
V_ASN1_OCTET_STRING, dig, diglen))
|
||||
{
|
||||
CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Verify signed receipt after it has already passed normal CMS verify */
|
||||
|
||||
int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
|
||||
|
@ -348,3 +370,52 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
|
|||
return r;
|
||||
|
||||
}
|
||||
|
||||
/* Encode a Receipt into an OCTET STRING read for including into content of
|
||||
* a SignedData ContentInfo.
|
||||
*/
|
||||
|
||||
ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
|
||||
{
|
||||
CMS_Receipt rct;
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
ASN1_OBJECT *ctype;
|
||||
ASN1_OCTET_STRING *os = NULL;
|
||||
|
||||
/* Get original receipt request */
|
||||
|
||||
/* Get original receipt request details */
|
||||
|
||||
if (!CMS_get1_ReceiptRequest(si, &rr))
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get original content type */
|
||||
|
||||
ctype = CMS_signed_get0_data_by_OBJ(si,
|
||||
OBJ_nid2obj(NID_pkcs9_contentType),
|
||||
-3, V_ASN1_OBJECT);
|
||||
if (!ctype)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rct.version = 1;
|
||||
rct.contentType = ctype;
|
||||
rct.signedContentIdentifier = rr->signedContentIdentifier;
|
||||
rct.originatorSignatureValue = si->signature;
|
||||
|
||||
os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL);
|
||||
|
||||
err:
|
||||
if (rr)
|
||||
CMS_ReceiptRequest_free(rr);
|
||||
|
||||
return os;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -450,6 +450,8 @@ int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
|
|||
const unsigned char *key, size_t keylen);
|
||||
|
||||
int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
|
||||
int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
|
||||
ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
|
||||
|
||||
BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
|
||||
|
||||
|
|
|
@ -471,6 +471,78 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
|
||||
X509 *signcert, EVP_PKEY *pkey,
|
||||
STACK_OF(X509) *certs,
|
||||
unsigned int flags)
|
||||
{
|
||||
CMS_SignerInfo *rct_si;
|
||||
CMS_ContentInfo *cms = NULL;
|
||||
ASN1_OCTET_STRING **pos, *os;
|
||||
BIO *rct_cont = NULL;
|
||||
int r = 0;
|
||||
|
||||
flags &= ~CMS_STREAM;
|
||||
/* Not really detached but avoids content being allocated */
|
||||
flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
|
||||
if (!pkey || !signcert)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize signed data */
|
||||
|
||||
cms = CMS_sign(NULL, NULL, certs, NULL, flags);
|
||||
if (!cms)
|
||||
goto err;
|
||||
|
||||
/* Set inner content type to signed receipt */
|
||||
if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
|
||||
goto err;
|
||||
|
||||
rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
|
||||
if (!rct_si)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
os = cms_encode_Receipt(si);
|
||||
|
||||
if (!os)
|
||||
goto err;
|
||||
|
||||
/* Set content to digest */
|
||||
rct_cont = BIO_new_mem_buf(os->data, os->length);
|
||||
if (!rct_cont)
|
||||
goto err;
|
||||
|
||||
/* Add msgSigDigest attribute */
|
||||
|
||||
if (!cms_msgSigDigest_add1(rct_si, si))
|
||||
goto err;
|
||||
|
||||
/* Finalize structure */
|
||||
if (!CMS_final(cms, rct_cont, flags))
|
||||
goto err;
|
||||
|
||||
/* Set embedded content */
|
||||
pos = CMS_get0_content(cms);
|
||||
*pos = os;
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
if (rct_cont)
|
||||
BIO_free(rct_cont);
|
||||
if (r)
|
||||
return cms;
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
|
||||
const EVP_CIPHER *cipher, unsigned int flags)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue