summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/cms.c8
-rw-r--r--crypto/build.info2
-rw-r--r--crypto/cms/cms_err.c4
-rw-r--r--crypto/cms/cms_ess.c73
-rw-r--r--crypto/cms/cms_sd.c21
-rw-r--r--crypto/err/err.c1
-rw-r--r--crypto/err/err_all.c2
-rw-r--r--crypto/err/openssl.ec1
-rw-r--r--crypto/err/openssl.txt19
-rw-r--r--crypto/ess/build.info3
-rw-r--r--crypto/ess/ess_asn1.c57
-rw-r--r--crypto/ess/ess_err.c53
-rw-r--r--crypto/ess/ess_lib.c269
-rw-r--r--crypto/include/internal/ess_int.h78
-rw-r--r--crypto/ts/ts_asn1.c41
-rw-r--r--crypto/ts/ts_err.c14
-rw-r--r--crypto/ts/ts_lcl.h61
-rw-r--r--crypto/ts/ts_rsp_sign.c250
-rw-r--r--crypto/ts/ts_rsp_verify.c32
-rw-r--r--doc/man1/cms.pod41
-rw-r--r--doc/man3/CMS_add1_signing_cert.pod45
-rw-r--r--include/openssl/cms.h6
-rw-r--r--include/openssl/cmserr.h2
-rw-r--r--include/openssl/err.h2
-rw-r--r--include/openssl/ess.h80
-rw-r--r--include/openssl/esserr.h38
-rw-r--r--include/openssl/ts.h48
-rw-r--r--include/openssl/tserr.h8
-rw-r--r--test/recipes/80-test_cms.t16
-rw-r--r--util/libcrypto.num55
30 files changed, 852 insertions, 478 deletions
diff --git a/apps/cms.c b/apps/cms.c
index 8402a272e2..b2037b4df2 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -65,7 +65,7 @@ struct cms_key_param_st {
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
- OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
+ OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
@@ -102,6 +102,7 @@ const OPTIONS cms_options[] = {
{"sign", OPT_SIGN, '-', "Sign message"},
{"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
{"resign", OPT_RESIGN, '-', "Resign a signed message"},
+ {"cades", OPT_CADES, '-', "Include signer certificate digest"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
{"verify_retcode", OPT_VERIFY_RETCODE, '-'},
{"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
@@ -326,6 +327,9 @@ int cms_main(int argc, char **argv)
case OPT_BINARY:
flags |= CMS_BINARY;
break;
+ case OPT_CADES:
+ flags |= CMS_CADES;
+ break;
case OPT_KEYID:
flags |= CMS_USE_KEYID;
break;
diff --git a/crypto/build.info b/crypto/build.info
index a0bb90acb4..e014e0336e 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
md2 md4 md5 sha mdc2 gmac hmac ripemd whrlpool poly1305 blake2 \
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
- err comp ocsp cms ts srp cmac ct async kmac
+ err comp ocsp cms ts srp cmac ct async kmac ess
LIBS=../libcrypto
SOURCE[../libcrypto]=\
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c
index 9596fab182..f7d4b7fd96 100644
--- a/crypto/cms/cms_err.c
+++ b/crypto/cms/cms_err.c
@@ -27,6 +27,10 @@ static const ERR_STRING_DATA CMS_str_functs[] = {
{ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNER, 0), "CMS_add1_signer"},
{ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNINGTIME, 0),
"cms_add1_signingTime"},
+ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNING_CERT, 0),
+ "CMS_add1_signing_cert"},
+ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNING_CERT_V2, 0),
+ "CMS_add1_signing_cert_v2"},
{ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESS, 0), "CMS_compress"},
{ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESSEDDATA_CREATE, 0),
"cms_CompressedData_create"},
diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c
index 86e88ffbbe..95e3628d9c 100644
--- a/crypto/cms/cms_ess.c
+++ b/crypto/cms/cms_ess.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -14,11 +14,13 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
+#include <openssl/ess.h>
#include "cms_lcl.h"
+#include "internal/ess_int.h"
IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
-/* ESS services: for now just Signed Receipt related */
+/* ESS services */
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
{
@@ -335,3 +337,70 @@ ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
CMS_ReceiptRequest_free(rr);
return os;
}
+
+/*
+ * Add signer certificate's V2 digest to a SignerInfo
+ * structure
+ */
+
+int CMS_add1_signing_cert_v2(CMS_SignerInfo *si,
+ ESS_SIGNING_CERT_V2 *sc)
+{
+ ASN1_STRING *seq = NULL;
+ unsigned char *p, *pp;
+ int len;
+
+ /* Add SigningCertificateV2 signed attribute to the signer info. */
+ len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
+ if ((pp = OPENSSL_malloc(len)) == NULL)
+ goto err;
+ p = pp;
+ i2d_ESS_SIGNING_CERT_V2(sc, &p);
+ if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len))
+ goto err;
+ OPENSSL_free(pp);
+ pp = NULL;
+ if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificateV2,
+ V_ASN1_SEQUENCE, seq, -1))
+ goto err;
+ ASN1_STRING_free(seq);
+ return 1;
+ err:
+ CMSerr(CMS_F_CMS_ADD1_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+}
+
+/*
+ * Add signer certificate's digest to a SignerInfo
+ * structure
+ */
+
+int CMS_add1_signing_cert(CMS_SignerInfo *si, ESS_SIGNING_CERT *sc)
+{
+ ASN1_STRING *seq = NULL;
+ unsigned char *p, *pp;
+ int len;
+
+ /* Add SigningCertificate signed attribute to the signer info. */
+ len = i2d_ESS_SIGNING_CERT(sc, NULL);
+ if ((pp = OPENSSL_malloc(len)) == NULL)
+ goto err;
+ p = pp;
+ i2d_ESS_SIGNING_CERT(sc, &p);
+ if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len))
+ goto err;
+ OPENSSL_free(pp);
+ pp = NULL;
+ if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificate,
+ V_ASN1_SEQUENCE, seq, -1))
+ goto err;
+ ASN1_STRING_free(seq);
+ return 1;
+ err:
+ CMSerr(CMS_F_CMS_ADD1_SIGNING_CERT, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+}
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
index f4f872efe8..71b3041116 100644
--- a/crypto/cms/cms_sd.c
+++ b/crypto/cms/cms_sd.c
@@ -332,6 +332,27 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
!CMS_SignerInfo_sign(si))
goto err;
}
+ if (flags & CMS_CADES) {
+ ESS_SIGNING_CERT *sc = NULL;
+ ESS_SIGNING_CERT_V2 *sc2 = NULL;
+ int add_sc;
+
+ if (md == EVP_sha1() || md == NULL) {
+ if ((sc = ESS_SIGNING_CERT_new_init(signer,
+ NULL, 1)) == NULL)
+ goto err;
+ add_sc = CMS_add1_signing_cert(si, sc);
+ ESS_SIGNING_CERT_free(sc);
+ } else {
+ if ((sc2 = ESS_SIGNING_CERT_V2_new_init(md, signer,
+ NULL, 1)) == NULL)
+ goto err;
+ add_sc = CMS_add1_signing_cert_v2(si, sc2);
+ ESS_SIGNING_CERT_V2_free(sc2);
+ }
+ if (!add_sc)
+ goto err;
+ }
}
if (!(flags & CMS_NOCERTS)) {
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 44e7115f9c..4505479772 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -64,6 +64,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
{ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
{ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
+ {ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
{0, NULL},
};
diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c
index 83ceff5c2e..3911ecc5c9 100644
--- a/crypto/err/err_all.c
+++ b/crypto/err/err_all.c
@@ -38,6 +38,7 @@
#include <openssl/asyncerr.h>
#include <openssl/kdferr.h>
#include <openssl/storeerr.h>
+#include <openssl/esserr.h>
int err_load_crypto_strings_int(void)
{
@@ -91,6 +92,7 @@ int err_load_crypto_strings_int(void)
# ifndef OPENSSL_NO_CT
ERR_load_CT_strings() == 0 ||
# endif
+ ERR_load_ESS_strings() == 0 ||
ERR_load_ASYNC_strings() == 0 ||
#endif
ERR_load_KDF_strings() == 0 ||
diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec
index 3e092eae0a..94d46d067b 100644
--- a/crypto/err/openssl.ec
+++ b/crypto/err/openssl.ec
@@ -34,6 +34,7 @@ L ASYNC include/openssl/async.h crypto/async/async_err.c
L KDF include/openssl/kdf.h crypto/kdf/kdf_err.c
L SM2 crypto/include/internal/sm2.h crypto/sm2/sm2_err.c
L OSSL_STORE include/openssl/store.h crypto/store/store_err.c
+L ESS include/openssl/ess.h crypto/ess/ess_err.c
# additional header files to be scanned for function names
L NONE include/openssl/x509_vfy.h NONE
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index fba1dc31f1..0e133d6e7d 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1,4 +1,4 @@
-# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
@@ -242,6 +242,8 @@ CMS_F_CMS_ADD1_RECEIPTREQUEST:158:CMS_add1_ReceiptRequest
CMS_F_CMS_ADD1_RECIPIENT_CERT:101:CMS_add1_recipient_cert
CMS_F_CMS_ADD1_SIGNER:102:CMS_add1_signer
CMS_F_CMS_ADD1_SIGNINGTIME:103:cms_add1_signingTime
+CMS_F_CMS_ADD1_SIGNING_CERT:181:CMS_add1_signing_cert
+CMS_F_CMS_ADD1_SIGNING_CERT_V2:182:CMS_add1_signing_cert_v2
CMS_F_CMS_COMPRESS:104:CMS_compress
CMS_F_CMS_COMPRESSEDDATA_CREATE:105:cms_CompressedData_create
CMS_F_CMS_COMPRESSEDDATA_INIT_BIO:106:cms_CompressedData_init_bio
@@ -709,6 +711,12 @@ ENGINE_F_INT_CTRL_HELPER:172:int_ctrl_helper
ENGINE_F_INT_ENGINE_CONFIGURE:188:int_engine_configure
ENGINE_F_INT_ENGINE_MODULE_INIT:187:int_engine_module_init
ENGINE_F_OSSL_HMAC_INIT:200:ossl_hmac_init
+ESS_F_ESS_CERT_ID_NEW_INIT:100:ESS_CERT_ID_new_init
+ESS_F_ESS_CERT_ID_V2_NEW_INIT:101:ESS_CERT_ID_V2_new_init
+ESS_F_ESS_SIGNING_CERT_ADD:104:ESS_SIGNING_CERT_add
+ESS_F_ESS_SIGNING_CERT_NEW_INIT:102:ESS_SIGNING_CERT_new_init
+ESS_F_ESS_SIGNING_CERT_V2_ADD:105:ESS_SIGNING_CERT_V2_add
+ESS_F_ESS_SIGNING_CERT_V2_NEW_INIT:103:ESS_SIGNING_CERT_V2_new_init
EVP_F_AESNI_INIT_KEY:165:aesni_init_key
EVP_F_AES_GCM_CTRL:196:aes_gcm_ctrl
EVP_F_AES_GCM_TLS_CIPHER:207:aes_gcm_tls_cipher
@@ -1558,12 +1566,6 @@ SSL_F_WPACKET_START_SUB_PACKET_LEN__:634:WPACKET_start_sub_packet_len__
SSL_F_WRITE_STATE_MACHINE:586:write_state_machine
TS_F_DEF_SERIAL_CB:110:def_serial_cb
TS_F_DEF_TIME_CB:111:def_time_cb
-TS_F_ESS_ADD_SIGNING_CERT:112:ess_add_signing_cert
-TS_F_ESS_ADD_SIGNING_CERT_V2:147:ess_add_signing_cert_v2
-TS_F_ESS_CERT_ID_NEW_INIT:113:ess_CERT_ID_new_init
-TS_F_ESS_CERT_ID_V2_NEW_INIT:156:ess_cert_id_v2_new_init
-TS_F_ESS_SIGNING_CERT_NEW_INIT:114:ess_SIGNING_CERT_new_init
-TS_F_ESS_SIGNING_CERT_V2_NEW_INIT:157:ess_signing_cert_v2_new_init
TS_F_INT_TS_RESP_VERIFY_TOKEN:149:int_ts_RESP_verify_token
TS_F_PKCS7_TO_TS_TST_INFO:148:PKCS7_to_TS_TST_INFO
TS_F_TS_ACCURACY_SET_MICROS:115:TS_ACCURACY_set_micros
@@ -2223,6 +2225,9 @@ ENGINE_R_UNIMPLEMENTED_CIPHER:146:unimplemented cipher
ENGINE_R_UNIMPLEMENTED_DIGEST:147:unimplemented digest
ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD:101:unimplemented public key method
ENGINE_R_VERSION_INCOMPATIBILITY:145:version incompatibility
+ESS_R_ESS_SIGNING_CERTIFICATE_ERROR:102:ess signing certificate error
+ESS_R_ESS_SIGNING_CERT_ADD_ERROR:100:ess signing cert add error
+ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR:101:ess signing cert v2 add error
EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed
EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed
EVP_R_BAD_DECRYPT:100:bad decrypt
diff --git a/crypto/ess/build.info b/crypto/ess/build.info
new file mode 100644
index 0000000000..24fcecc8f5
--- /dev/null
+++ b/crypto/ess/build.info
@@ -0,0 +1,3 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]= \
+ ess_lib.c ess_asn1.c ess_err.c
diff --git a/crypto/ess/ess_asn1.c b/crypto/ess/ess_asn1.c
new file mode 100644
index 0000000000..d10746906a
--- /dev/null
+++ b/crypto/ess/ess_asn1.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/asn1t.h>
+#include <openssl/ess.h>
+#include <openssl/x509v3.h>
+#include "internal/ess_int.h"
+
+/* ASN1 stuff for ESS Structure */
+
+ASN1_SEQUENCE(ESS_ISSUER_SERIAL) = {
+ ASN1_SEQUENCE_OF(ESS_ISSUER_SERIAL, issuer, GENERAL_NAME),
+ ASN1_SIMPLE(ESS_ISSUER_SERIAL, serial, ASN1_INTEGER)
+} static_ASN1_SEQUENCE_END(ESS_ISSUER_SERIAL)
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ESS_ISSUER_SERIAL)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_ISSUER_SERIAL)
+
+ASN1_SEQUENCE(ESS_CERT_ID) = {
+ ASN1_SIMPLE(ESS_CERT_ID, hash, ASN1_OCTET_STRING),
+ ASN1_OPT(ESS_CERT_ID, issuer_serial, ESS_ISSUER_SERIAL)
+} static_ASN1_SEQUENCE_END(ESS_CERT_ID)
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID)
+
+ASN1_SEQUENCE(ESS_SIGNING_CERT) = {
+ ASN1_SEQUENCE_OF(ESS_SIGNING_CERT, cert_ids, ESS_CERT_ID),
+ ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT, policy_info, POLICYINFO)
+} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT)
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT)
+
+ASN1_SEQUENCE(ESS_CERT_ID_V2) = {
+ ASN1_OPT(ESS_CERT_ID_V2, hash_alg, X509_ALGOR),
+ ASN1_SIMPLE(ESS_CERT_ID_V2, hash, ASN1_OCTET_STRING),
+ ASN1_OPT(ESS_CERT_ID_V2, issuer_serial, ESS_ISSUER_SERIAL)
+} static_ASN1_SEQUENCE_END(ESS_CERT_ID_V2)
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID_V2)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2)
+
+ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = {
+ ASN1_SEQUENCE_OF(ESS_SIGNING_CERT_V2, cert_ids, ESS_CERT_ID_V2),
+ ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT_V2, policy_info, POLICYINFO)
+} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT_V2)
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT_V2)
+IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2)
diff --git a/crypto/ess/ess_err.c b/crypto/ess/ess_err.c
new file mode 100644
index 0000000000..215b7f1ebc
--- /dev/null
+++ b/crypto/ess/ess_err.c
@@ -0,0 +1,53 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/esserr.h>
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA ESS_str_functs[] = {
+ {ERR_PACK(ERR_LIB_ESS, ESS_F_ESS_CERT_ID_NEW_INIT, 0),
+ "ESS_CERT_ID_new_init"},
+ {ERR_PACK(ERR_LIB_ESS, ESS_F_ESS_CERT_ID_V2_NEW_INIT, 0),
+ "ESS_CERT_ID_V2_new_init"},
+ {ERR_PACK(ERR_LIB_ESS, ESS_F_ESS_SIGNING_CERT_ADD, 0),
+ "ESS_SIGNING_CERT_add"},
+ {ERR_PACK(ERR_LIB_ESS, ESS_F_ESS_SIGNING_CERT_NEW_INIT, 0),
+ "ESS_SIGNING_CERT_new_init"},
+ {ERR_PACK(ERR_LIB_ESS, ESS_F_ESS_SIGNING_CERT_V2_ADD, 0),
+ "ESS_SIGNING_CERT_V2_add"},
+ {ERR_PACK(ERR_LIB_ESS, ESS_F_ESS_SIGNING_CERT_V2_NEW_INIT, 0),
+ "ESS_SIGNING_CERT_V2_new_init"},
+ {0, NULL}
+};
+
+static const ERR_STRING_DATA ESS_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERTIFICATE_ERROR),
+ "ess signing certificate error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERT_ADD_ERROR),
+ "ess signing cert add error"},
+ {ERR_PACK(ERR_LIB_ESS, 0, ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR),
+ "ess signing cert v2 add error"},
+ {0, NULL}
+};
+
+#endif
+
+int ERR_load_ESS_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+ if (ERR_func_error_string(ESS_str_functs[0].error) == NULL) {
+ ERR_load_strings_const(ESS_str_functs);
+ ERR_load_strings_const(ESS_str_reasons);
+ }
+#endif
+ return 1;
+}
diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c
new file mode 100644
index 0000000000..fa9cff18be
--- /dev/null
+++ b/crypto/ess/ess_lib.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/ess.h>
+#include "internal/ess_int.h"
+
+static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed);
+static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
+ X509 *cert, int issuer_needed);
+
+ESS_SIGNING_CERT *ESS_SIGNING_CERT_new_init(X509 *signcert,
+ STACK_OF(X509) *certs,
+ int issuer_needed)
+{
+ ESS_CERT_ID *cid = NULL;
+ ESS_SIGNING_CERT *sc;
+ int i;
+
+ if ((sc = ESS_SIGNING_CERT_new()) == NULL)
+ goto err;
+ if (sc->cert_ids == NULL
+ && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL)
+ goto err;
+
+ if ((cid = ESS_CERT_ID_new_init(signcert, issuer_needed)) == NULL
+ || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
+ goto err;
+ for (i = 0; i < sk_X509_num(certs); ++i) {
+ X509 *cert = sk_X509_value(certs, i);
+ if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL
+ || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
+ goto err;
+ }
+
+ return sc;
+ err:
+ ESS_SIGNING_CERT_free(sc);
+ ESS_CERT_ID_free(cid);
+ ESSerr(ESS_F_ESS_SIGNING_CERT_NEW_INIT, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
+{
+ ESS_CERT_ID *cid = NULL;
+ GENERAL_NAME *name = NULL;
+ unsigned char cert_sha1[SHA_DIGEST_LENGTH];
+
+ /* Call for side-effect of computing hash and caching extensions */
+ X509_check_purpose(cert, -1, 0);
+ if ((cid = ESS_CERT_ID_new()) == NULL)
+ goto err;
+ X509_digest(cert, EVP_sha1(), cert_sha1, NULL);
+ if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH))
+ goto err;
+
+ /* Setting the issuer/serial if requested. */
+ if (!issuer_needed)
+ return cid;
+
+ if (cid->issuer_serial == NULL
+ && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
+ goto err;
+ if ((name = GENERAL_NAME_new()) == NULL)
+ goto err;
+ name->type = GEN_DIRNAME;
+ if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
+ goto err;
+ if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
+ goto err;
+ name = NULL; /* Ownership is lost. */
+ ASN1_INTEGER_free(cid->issuer_serial->serial);
+ if (!(cid->issuer_serial->serial =
+ ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
+ goto err;
+
+ return cid;
+ err:
+ GENERAL_NAME_free(name);
+ ESS_CERT_ID_free(cid);
+ ESSerr(ESS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new_init(const EVP_MD *hash_alg,
+ X509 *signcert,
+ STACK_OF(X509) *certs,
+ int issuer_needed)
+{
+ ESS_CERT_ID_V2 *cid = NULL;
+ ESS_SIGNING_CERT_V2 *sc;
+ int i;
+
+ if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL)
+ goto err;
+ if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, signcert, issuer_needed)) == NULL)
+ goto err;
+ if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
+ goto err;
+ cid = NULL;
+
+ for (i = 0; i < sk_X509_num(certs); ++i) {
+ X509 *cert = sk_X509_value(certs, i);
+
+ if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL)
+ goto err;
+ if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
+ goto err;
+ cid = NULL;
+ }
+
+ return sc;
+ err:
+ ESS_SIGNING_CERT_V2_free(sc);
+ ESS_CERT_ID_V2_free(cid);
+ ESSerr(ESS_F_ESS_SIGNING_CERT_V2_NEW_INIT, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
+ X509 *cert, int issuer_needed)
+{
+ ESS_CERT_ID_V2 *cid;
+ GENERAL_NAME *name = NULL;
+ unsigned char hash[EVP_MAX_MD_SIZE];
+ unsigned int hash_len = sizeof(hash);
+ X509_ALGOR *alg = NULL;
+
+ memset(hash, 0, sizeof(hash));
+
+ if ((cid = ESS_CERT_ID_V2_new()) == NULL)
+ goto err;
+
+ if (hash_alg != EVP_sha256()) {
+ alg = X509_ALGOR_new();
+ if (alg == NULL)
+ goto err;
+ X509_ALGOR_set_md(alg, hash_alg);
+ if (alg->algorithm == NULL)
+ goto err;
+ cid->hash_alg = alg;
+ alg = NULL;
+ } else {
+ cid->hash_alg = NULL;
+ }
+
+ if (!X509_digest(cert, hash_alg, hash, &hash_len))
+ goto err;
+
+ if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len))
+ goto err;
+
+ if (!issuer_needed)
+ return cid;
+
+ if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
+ goto err;
+ if ((name = GENERAL_NAME_new()) == NULL)
+ goto err;
+ name->type = GEN_DIRNAME;
+ if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
+ goto err;
+ if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
+ goto err;
+ name = NULL; /* Ownership is lost. */
+ ASN1_INTEGER_free(cid->issuer_serial->serial);
+ cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+ if (cid->issuer_serial->serial == NULL)
+ goto err;
+
+ return cid;
+ err:
+ X509_ALGOR_free(alg);
+ GENERAL_NAME_free(name);
+ ESS_CERT_ID_V2_free(cid);
+ ESSerr(ESS_F_ESS_CERT_ID_V2_NEW_INIT, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+ESS_SIGNING_CERT *ESS_SIGNING_CERT_get(PKCS7_SIGNER_INFO *si)
+{
+ ASN1_TYPE *attr;
+ const unsigned char *p;
+ attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate);
+ if (!attr)
+ return NULL;
+ p = attr->value.sequence->data;
+ return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
+}
+
+ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_get(PKCS7_SIGNER_INFO *si)
+{
+ ASN1_TYPE *attr;
+ const unsigned char *p;
+
+ attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2);
+ if (attr == NULL)
+ return NULL;
+ p = attr->value.sequence->data;
+ return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length);
+}
+
+int ESS_SIGNING_CERT_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc)
+{
+ ASN1_STRING *seq = NULL;
+ unsigned char *p, *pp = NULL;
+ int len;
+
+ len = i2d_ESS_SIGNING_CERT(sc, NULL);
+ if ((pp = OPENSSL_malloc(len)) == NULL) {
+ ESSerr(ESS_F_ESS_SIGNING_CERT_ADD, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ p = pp;
+ i2d_ESS_SIGNING_CERT(sc, &p);
+ if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
+ ESSerr(ESS_F_ESS_SIGNING_CERT_ADD, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ OPENSSL_free(pp);
+ pp = NULL;
+ return PKCS7_add_signed_attribute(si,
+ NID_id_smime_aa_signingCertificate,
+ V_ASN1_SEQUENCE, seq);
+ err:
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+
+ return 0;
+}
+
+int ESS_SIGNING_CERT_V2_add(PKCS7_SIGNER_INFO *si,
+ ESS_SIGNING_CERT_V2 *sc)
+{
+ ASN1_STRING *seq = NULL;
+ unsigned char *p, *pp = NULL;
+ int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
+
+ if ((pp = OPENSSL_malloc(len)) == NULL) {
+ ESSerr(ESS_F_ESS_SIGNING_CERT_V2_ADD, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = pp;
+ i2d_ESS_SIGNING_CERT_V2(sc, &p);
+ if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
+ ESSerr(ESS_F_ESS_SIGNING_CERT_V2_ADD, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ OPENSSL_free(pp);
+ pp = NULL;
+ return PKCS7_add_signed_attribute(si,
+ NID_id_smime_aa_signingCertificateV2,
+ V_ASN1_SEQUENCE, seq);
+ err:
+ ASN1_STRING_free(seq);
+ OPENSSL_free(pp);
+ return 0;
+}
diff --git a/crypto/include/internal/ess_int.h b/crypto/include/internal/ess_int.h
new file mode 100644
index 0000000000..26476ae984
--- /dev/null
+++ b/crypto/include/internal/ess_int.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* internal ESS related stuff */
+
+ESS_SIGNING_CERT *ESS_SIGNING_CERT_get(PKCS7_SIGNER_INFO *si);
+int ESS_SIGNING_CERT_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc);
+
+ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_get(PKCS7_SIGNER_INFO *si);
+int ESS_SIGNING_CERT_V2_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT_V2 *sc);
+
+/*-
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ */
+
+struct ESS_issuer_serial {
+ STACK_OF(GENERAL_NAME) *issuer;
+ ASN1_INTEGER *serial;
+};
+
+/*-
+ * ESSCertID ::= SEQUENCE {
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ */
+
+struct ESS_cert_id {
+ ASN1_OCTET_STRING *hash; /* Always SHA-1 digest. */
+ ESS_ISSUER_SERIAL *issuer_serial;
+};
+
+/*-
+ * SigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ */
+
+struct ESS_signing_cert {
+ STACK_OF(ESS_CERT_ID) *cert_ids;
+ STACK_OF(POLICYINFO) *policy_info;
+};
+
+/*-
+ * ESSCertIDv2 ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier DEFAULT id-sha256,
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ */
+
+struct ESS_cert_id_v2_st {
+ X509_ALGOR *hash_alg; /* Default: SHA-256 */
+ ASN1_OCTET_STRING *hash;
+ ESS_ISSUER_SERIAL *issuer_serial;
+};
+