PKCS9_SEQUENCE_NUMBER authenticated attribute support

This commit is contained in:
olszomal 2024-01-22 14:00:48 +01:00 committed by Michał Trojnara
parent 0985c47990
commit 44ca1f38e6
8 changed files with 122 additions and 8 deletions

View File

@ -10,6 +10,7 @@
- added CAT file verification and listing each member of the CAT file - added CAT file verification and listing each member of the CAT file
by using the "-verbose" option by using the "-verbose" option
- added new command "extract-data" to extract a PKCS#7 data content to be signed - added new command "extract-data" to extract a PKCS#7 data content to be signed
- PKCS9_SEQUENCE_NUMBER authenticated attribute support
### 2.7 (2023.09.19) ### 2.7 (2023.09.19)

6
cab.c
View File

@ -506,6 +506,12 @@ static PKCS7 *cab_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
printf("Unable to extract existing signature\n"); printf("Unable to extract existing signature\n");
return NULL; /* FAILED */ return NULL; /* FAILED */
} }
ctx->options->nested_number = nested_signatures_number_get(cursig);
if (ctx->options->nested_number < 0) {
printf("Unable to get number of nested signatures\n");
PKCS7_free(cursig);
return NULL; /* FAILED */
}
if (ctx->options->cmd == CMD_ADD) if (ctx->options->cmd == CMD_ADD)
p7 = cursig; p7 = cursig;
} }

View File

@ -14,6 +14,7 @@ static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT
static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx); static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
static int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx); static int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx); static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
static int pkcs7_signer_info_add_sequence_number(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer); static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer);
static int X509_compare(const X509 *const *a, const X509 *const *b); static int X509_compare(const X509 *const *a, const X509 *const *b);
@ -237,6 +238,10 @@ PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
printf("Couldn't allocate memory for opus info\n"); printf("Couldn't allocate memory for opus info\n");
return NULL; /* FAILED */ return NULL; /* FAILED */
} }
if ((ctx->options->nested_number >= 0) &&
!pkcs7_signer_info_add_sequence_number(si, ctx)) {
return NULL; /* FAILED */
}
/* create X509 chain sorted in ascending order by their DER encoding */ /* create X509 chain sorted in ascending order by their DER encoding */
chain = X509_chain_get_sorted(ctx, signer); chain = X509_chain_get_sorted(ctx, signer);
if (chain == NULL) { if (chain == NULL) {
@ -719,6 +724,25 @@ static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX
V_ASN1_SEQUENCE, purpose); V_ASN1_SEQUENCE, purpose);
} }
/*
* [in, out] si: PKCS7_SIGNER_INFO structure
* [in] ctx: structure holds input and output data
* [returns] 0 on error or 1 on success
*/
static int pkcs7_signer_info_add_sequence_number(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
{
ASN1_INTEGER *number = ASN1_INTEGER_new();
if (!number)
return 0; /* FAILED */
if (!ASN1_INTEGER_set(number, ctx->options->nested_number + 1)) {
ASN1_INTEGER_free(number);
return 0; /* FAILED */
}
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(PKCS9_SEQUENCE_NUMBER),
V_ASN1_INTEGER, number);
}
/* /*
* Create certificate chain sorted in ascending order by their DER encoding. * Create certificate chain sorted in ascending order by their DER encoding.
* [in] ctx: structure holds input and output data * [in] ctx: structure holds input and output data
@ -794,6 +818,37 @@ static int X509_compare(const X509 *const *a, const X509 *const *b)
return ret; return ret;
} }
/*
* Return the number of objects in SPC_NESTED_SIGNATURE_OBJID attribute
* [in] p7: existing PKCS#7 signature (Primary Signature)
* [returns] -1 on error or the number of nested signatures
*/
int nested_signatures_number_get(PKCS7 *p7)
{
int i;
STACK_OF(X509_ATTRIBUTE) *unauth_attr;
PKCS7_SIGNER_INFO *si;
STACK_OF(PKCS7_SIGNER_INFO) *signer_info = PKCS7_get_signer_info(p7);
if (!signer_info)
return -1; /* FAILED */
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
if (!si)
return -1; /* FAILED */
unauth_attr = PKCS7_get_attributes(si); /* cont[1] */
if (!unauth_attr)
return 0; /* OK, no unauthenticated attributes */
for (i=0; i<X509at_get_attr_count(unauth_attr); i++) {
int nid = OBJ_txt2nid(SPC_NESTED_SIGNATURE_OBJID);
X509_ATTRIBUTE *attr = X509at_get_attr(unauth_attr, i);
if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid) {
/* Nested Signature - Policy OID: 1.3.6.1.4.1.311.2.4.1 */
return X509_ATTRIBUTE_count(attr);
}
}
return 0; /* OK, no SPC_NESTED_SIGNATURE_OBJID attribute */
}
/* /*
Local Variables: Local Variables:
c-basic-offset: 4 c-basic-offset: 4

View File

@ -26,6 +26,7 @@ MsCtlContent *ms_ctl_content_get(PKCS7 *p7);
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute); ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
SpcLink *spc_link_obsolete_get(void); SpcLink *spc_link_obsolete_get(void);
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype); int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
int nested_signatures_number_get(PKCS7 *p7);
/* /*
Local Variables: Local Variables:

6
msi.c
View File

@ -676,6 +676,12 @@ static PKCS7 *msi_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
PKCS7_free(cursig); PKCS7_free(cursig);
return NULL; /* FAILED */ return NULL; /* FAILED */
} }
ctx->options->nested_number = nested_signatures_number_get(cursig);
if (ctx->options->nested_number < 0) {
printf("Unable to get number of nested signatures\n");
PKCS7_free(cursig);
return NULL; /* FAILED */
}
if (ctx->options->cmd == CMD_ADD) if (ctx->options->cmd == CMD_ADD)
p7 = cursig; p7 = cursig;
} }

View File

@ -2037,8 +2037,10 @@ static time_t time_t_timestamp_get_attributes(CMS_ContentInfo **timestamp, PKCS7
md_nid = OBJ_obj2nid(si->digest_alg->algorithm); md_nid = OBJ_obj2nid(si->digest_alg->algorithm);
printf("Message digest algorithm: %s\n", printf("Message digest algorithm: %s\n",
(md_nid == NID_undef) ? "UNKNOWN" : OBJ_nid2sn(md_nid)); (md_nid == NID_undef) ? "UNKNOWN" : OBJ_nid2sn(md_nid));
printf("\nAuthenticated attributes:\n");
/* Unauthenticated attributes */
auth_attr = PKCS7_get_signed_attributes(si); /* cont[0] */ auth_attr = PKCS7_get_signed_attributes(si); /* cont[0] */
printf("\nAuthenticated attributes:\n");
for (i=0; i<X509at_get_attr_count(auth_attr); i++) { for (i=0; i<X509at_get_attr_count(auth_attr); i++) {
attr = X509at_get_attr(auth_attr, i); attr = X509at_get_attr(auth_attr, i);
object = X509_ATTRIBUTE_get0_object(attr); object = X509_ATTRIBUTE_get0_object(attr);
@ -2121,6 +2123,12 @@ static time_t time_t_timestamp_get_attributes(CMS_ContentInfo **timestamp, PKCS7
printf("\tLow level of permissions in Microsoft Internet Explorer 4.x for CAB files\n"); printf("\tLow level of permissions in Microsoft Internet Explorer 4.x for CAB files\n");
else else
printf("\tUnrecognized level of permissions in Microsoft Internet Explorer 4.x for CAB files\n"); printf("\tUnrecognized level of permissions in Microsoft Internet Explorer 4.x for CAB files\n");
} else if (!strcmp(object_txt, PKCS9_SEQUENCE_NUMBER)) {
/* PKCS#9 sequence number - Policy OID: 1.2.840.113549.1.9.25.4 */
ASN1_INTEGER *number = X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_INTEGER, NULL);
if (number == NULL)
continue;
printf("\tSequence number: %ld\n", ASN1_INTEGER_get(number));
} }
} }
@ -2247,15 +2255,13 @@ static time_t time_t_get_si_time(PKCS7_SIGNER_INFO *si)
} }
/* /*
* Get signing time from authenticated attributes * Get signing time from authenticated attributes cont[0]
* [in] si: PKCS7_SIGNER_INFO structure * [in] si: PKCS7_SIGNER_INFO structure
* [returns] NULL on error or ASN1_UTCTIME on success * [returns] NULL on error or ASN1_UTCTIME on success
*/ */
static ASN1_UTCTIME *asn1_time_get_si_time(PKCS7_SIGNER_INFO *si) static ASN1_UTCTIME *asn1_time_get_si_time(PKCS7_SIGNER_INFO *si)
{ {
STACK_OF(X509_ATTRIBUTE) *auth_attr; STACK_OF(X509_ATTRIBUTE) *auth_attr = PKCS7_get_signed_attributes(si);
auth_attr = PKCS7_get_signed_attributes(si); /* cont[0] */
if (auth_attr) { if (auth_attr) {
int i; int i;
for (i=0; i<X509at_get_attr_count(auth_attr); i++) { for (i=0; i<X509at_get_attr_count(auth_attr); i++) {
@ -2270,6 +2276,28 @@ static ASN1_UTCTIME *asn1_time_get_si_time(PKCS7_SIGNER_INFO *si)
return NULL; return NULL;
} }
/*
* Get sequence number from authenticated attributes cont[0]
* [in] si: PKCS7_SIGNER_INFO structure
* [returns] NULL on error or ASN1_UTCTIME on success
*/
static long get_sequence_number(PKCS7_SIGNER_INFO *si)
{
STACK_OF(X509_ATTRIBUTE) *auth_attr = PKCS7_get_signed_attributes(si);
if (auth_attr) {
int i;
for (i=0; i<X509at_get_attr_count(auth_attr); i++) {
int nid = OBJ_txt2nid(PKCS9_SEQUENCE_NUMBER);
X509_ATTRIBUTE *attr = X509at_get_attr(auth_attr, i);
if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid) {
/* PKCS#9 sequence number - Policy OID:1.2.840.113549.1.9.25.4 */
return ASN1_INTEGER_get(X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_INTEGER, NULL));
}
}
}
return 0;
}
/* /*
* Get timestamping time from embedded content in a CMS_ContentInfo structure * Get timestamping time from embedded content in a CMS_ContentInfo structure
* [in] si: CMS_ContentInfo structure * [in] si: CMS_ContentInfo structure
@ -2701,6 +2729,7 @@ static int PKCS7_compare(const PKCS7 *const *a, const PKCS7 *const *b)
STACK_OF(PKCS7_SIGNER_INFO) *signer_info; STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
PKCS7_SIGNER_INFO *si; PKCS7_SIGNER_INFO *si;
const ASN1_TIME *time_a, *time_b; const ASN1_TIME *time_a, *time_b;
long index_a, index_b;
int ret = 0; int ret = 0;
p7_a = PKCS7_dup(*a); p7_a = PKCS7_dup(*a);
@ -2713,6 +2742,7 @@ static int PKCS7_compare(const PKCS7 *const *a, const PKCS7 *const *b)
if (!si) if (!si)
goto out; goto out;
time_a = asn1_time_get_si_time(si); time_a = asn1_time_get_si_time(si);
index_a = get_sequence_number(si);
p7_b = PKCS7_dup(*b); p7_b = PKCS7_dup(*b);
if (!p7_b) if (!p7_b)
@ -2724,7 +2754,12 @@ static int PKCS7_compare(const PKCS7 *const *a, const PKCS7 *const *b)
if (!si) if (!si)
goto out; goto out;
time_b = asn1_time_get_si_time(si); time_b = asn1_time_get_si_time(si);
ret = ASN1_TIME_compare(time_b, time_a); index_b = get_sequence_number(si);
if (index_a == index_b)
ret = ASN1_TIME_compare(time_a, time_b);
else
ret = (index_a == 0 || index_a < index_b) ? 1 : -1;
out: out:
PKCS7_free(p7_a); PKCS7_free(p7_a);
@ -3811,6 +3846,7 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
options->time = INVALID_TIME; options->time = INVALID_TIME;
options->jp = -1; options->jp = -1;
options->index = -1; options->index = -1;
options->nested_number = -1;
#if OPENSSL_VERSION_NUMBER>=0x30000000L #if OPENSSL_VERSION_NUMBER>=0x30000000L
/* Use legacy PKCS#12 container with RC2-40-CBC private key and certificate encryption algorithm */ /* Use legacy PKCS#12 container with RC2-40-CBC private key and certificate encryption algorithm */
options->legacy = 1; options->legacy = 1;
@ -4194,7 +4230,8 @@ int main(int argc, char **argv)
|| !OBJ_create(SPC_SP_OPUS_INFO_OBJID, NULL, NULL) || !OBJ_create(SPC_SP_OPUS_INFO_OBJID, NULL, NULL)
|| !OBJ_create(SPC_NESTED_SIGNATURE_OBJID, NULL, NULL) || !OBJ_create(SPC_NESTED_SIGNATURE_OBJID, NULL, NULL)
|| !OBJ_create(SPC_UNAUTHENTICATED_DATA_BLOB_OBJID, NULL, NULL) || !OBJ_create(SPC_UNAUTHENTICATED_DATA_BLOB_OBJID, NULL, NULL)
|| !OBJ_create(SPC_RFC3161_OBJID, NULL, NULL)) || !OBJ_create(SPC_RFC3161_OBJID, NULL, NULL)
|| !OBJ_create(PKCS9_SEQUENCE_NUMBER, NULL, NULL))
DO_EXIT_0("Failed to create objects\n"); DO_EXIT_0("Failed to create objects\n");
/* commands and options initialization */ /* commands and options initialization */

View File

@ -187,6 +187,7 @@
#define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4" #define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
#define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5" #define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5"
#define PKCS9_COUNTER_SIGNATURE "1.2.840.113549.1.9.6" #define PKCS9_COUNTER_SIGNATURE "1.2.840.113549.1.9.6"
#define PKCS9_SEQUENCE_NUMBER "1.2.840.113549.1.9.25.4"
/* WIN_CERTIFICATE structure declared in Wintrust.h */ /* WIN_CERTIFICATE structure declared in Wintrust.h */
#define WIN_CERT_REVISION_2_0 0x0200 #define WIN_CERT_REVISION_2_0 0x0200
@ -291,6 +292,7 @@ typedef struct {
char *tsa_certfile; char *tsa_certfile;
char *tsa_keyfile; char *tsa_keyfile;
time_t tsa_time; time_t tsa_time;
int nested_number;
} GLOBAL_OPTIONS; } GLOBAL_OPTIONS;
/* /*

6
pe.c
View File

@ -423,6 +423,12 @@ static PKCS7 *pe_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
printf("Unable to extract existing signature\n"); printf("Unable to extract existing signature\n");
return NULL; /* FAILED */ return NULL; /* FAILED */
} }
ctx->options->nested_number = nested_signatures_number_get(cursig);
if (ctx->options->nested_number < 0) {
printf("Unable to get number of nested signatures\n");
PKCS7_free(cursig);
return NULL; /* FAILED */
}
if (ctx->options->cmd == CMD_ADD) if (ctx->options->cmd == CMD_ADD)
p7 = cursig; p7 = cursig;
} }