1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 11e1051a39Sopenharmony_ci#include <openssl/pem.h> 12e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 13e1051a39Sopenharmony_ci#include <openssl/err.h> 14e1051a39Sopenharmony_ci#include <openssl/cms.h> 15e1051a39Sopenharmony_ci#include "cms_local.h" 16e1051a39Sopenharmony_ci#include "internal/nelem.h" 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/*- 19e1051a39Sopenharmony_ci * Attribute flags. 20e1051a39Sopenharmony_ci * CMS attribute restrictions are discussed in 21e1051a39Sopenharmony_ci * - RFC 5652 Section 11. 22e1051a39Sopenharmony_ci * ESS attribute restrictions are discussed in 23e1051a39Sopenharmony_ci * - RFC 2634 Section 1.3.4 AND 24e1051a39Sopenharmony_ci * - RFC 5035 Section 5.4 25e1051a39Sopenharmony_ci */ 26e1051a39Sopenharmony_ci/* This is a signed attribute */ 27e1051a39Sopenharmony_ci#define CMS_ATTR_F_SIGNED 0x01 28e1051a39Sopenharmony_ci/* This is an unsigned attribute */ 29e1051a39Sopenharmony_ci#define CMS_ATTR_F_UNSIGNED 0x02 30e1051a39Sopenharmony_ci/* Must be present if there are any other attributes of the same type */ 31e1051a39Sopenharmony_ci#define CMS_ATTR_F_REQUIRED_COND 0x10 32e1051a39Sopenharmony_ci/* There can only be one instance of this attribute */ 33e1051a39Sopenharmony_ci#define CMS_ATTR_F_ONLY_ONE 0x20 34e1051a39Sopenharmony_ci/* The Attribute's value must have exactly one entry */ 35e1051a39Sopenharmony_ci#define CMS_ATTR_F_ONE_ATTR_VALUE 0x40 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci/* Attributes rules for different attributes */ 38e1051a39Sopenharmony_cistatic const struct { 39e1051a39Sopenharmony_ci int nid; /* The attribute id */ 40e1051a39Sopenharmony_ci int flags; 41e1051a39Sopenharmony_ci} cms_attribute_properties[] = { 42e1051a39Sopenharmony_ci /* See RFC Section 11 */ 43e1051a39Sopenharmony_ci { NID_pkcs9_contentType, CMS_ATTR_F_SIGNED 44e1051a39Sopenharmony_ci | CMS_ATTR_F_ONLY_ONE 45e1051a39Sopenharmony_ci | CMS_ATTR_F_ONE_ATTR_VALUE 46e1051a39Sopenharmony_ci | CMS_ATTR_F_REQUIRED_COND }, 47e1051a39Sopenharmony_ci { NID_pkcs9_messageDigest, CMS_ATTR_F_SIGNED 48e1051a39Sopenharmony_ci | CMS_ATTR_F_ONLY_ONE 49e1051a39Sopenharmony_ci | CMS_ATTR_F_ONE_ATTR_VALUE 50e1051a39Sopenharmony_ci | CMS_ATTR_F_REQUIRED_COND }, 51e1051a39Sopenharmony_ci { NID_pkcs9_signingTime, CMS_ATTR_F_SIGNED 52e1051a39Sopenharmony_ci | CMS_ATTR_F_ONLY_ONE 53e1051a39Sopenharmony_ci | CMS_ATTR_F_ONE_ATTR_VALUE }, 54e1051a39Sopenharmony_ci { NID_pkcs9_countersignature, CMS_ATTR_F_UNSIGNED }, 55e1051a39Sopenharmony_ci /* ESS */ 56e1051a39Sopenharmony_ci { NID_id_smime_aa_signingCertificate, CMS_ATTR_F_SIGNED 57e1051a39Sopenharmony_ci | CMS_ATTR_F_ONLY_ONE 58e1051a39Sopenharmony_ci | CMS_ATTR_F_ONE_ATTR_VALUE }, 59e1051a39Sopenharmony_ci { NID_id_smime_aa_signingCertificateV2, CMS_ATTR_F_SIGNED 60e1051a39Sopenharmony_ci | CMS_ATTR_F_ONLY_ONE 61e1051a39Sopenharmony_ci | CMS_ATTR_F_ONE_ATTR_VALUE }, 62e1051a39Sopenharmony_ci { NID_id_smime_aa_receiptRequest, CMS_ATTR_F_SIGNED 63e1051a39Sopenharmony_ci | CMS_ATTR_F_ONLY_ONE 64e1051a39Sopenharmony_ci | CMS_ATTR_F_ONE_ATTR_VALUE } 65e1051a39Sopenharmony_ci}; 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci/* CMS SignedData Attribute utilities */ 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ciint CMS_signed_get_attr_count(const CMS_SignerInfo *si) 70e1051a39Sopenharmony_ci{ 71e1051a39Sopenharmony_ci return X509at_get_attr_count(si->signedAttrs); 72e1051a39Sopenharmony_ci} 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ciint CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, int lastpos) 75e1051a39Sopenharmony_ci{ 76e1051a39Sopenharmony_ci return X509at_get_attr_by_NID(si->signedAttrs, nid, lastpos); 77e1051a39Sopenharmony_ci} 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ciint CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj, 80e1051a39Sopenharmony_ci int lastpos) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci return X509at_get_attr_by_OBJ(si->signedAttrs, obj, lastpos); 83e1051a39Sopenharmony_ci} 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ciX509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc) 86e1051a39Sopenharmony_ci{ 87e1051a39Sopenharmony_ci return X509at_get_attr(si->signedAttrs, loc); 88e1051a39Sopenharmony_ci} 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ciX509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc) 91e1051a39Sopenharmony_ci{ 92e1051a39Sopenharmony_ci return X509at_delete_attr(si->signedAttrs, loc); 93e1051a39Sopenharmony_ci} 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_ciint CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr) 96e1051a39Sopenharmony_ci{ 97e1051a39Sopenharmony_ci if (X509at_add1_attr(&si->signedAttrs, attr)) 98e1051a39Sopenharmony_ci return 1; 99e1051a39Sopenharmony_ci return 0; 100e1051a39Sopenharmony_ci} 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ciint CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, 103e1051a39Sopenharmony_ci const ASN1_OBJECT *obj, int type, 104e1051a39Sopenharmony_ci const void *bytes, int len) 105e1051a39Sopenharmony_ci{ 106e1051a39Sopenharmony_ci if (X509at_add1_attr_by_OBJ(&si->signedAttrs, obj, type, bytes, len)) 107e1051a39Sopenharmony_ci return 1; 108e1051a39Sopenharmony_ci return 0; 109e1051a39Sopenharmony_ci} 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ciint CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, 112e1051a39Sopenharmony_ci int nid, int type, const void *bytes, int len) 113e1051a39Sopenharmony_ci{ 114e1051a39Sopenharmony_ci if (X509at_add1_attr_by_NID(&si->signedAttrs, nid, type, bytes, len)) 115e1051a39Sopenharmony_ci return 1; 116e1051a39Sopenharmony_ci return 0; 117e1051a39Sopenharmony_ci} 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ciint CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, 120e1051a39Sopenharmony_ci const char *attrname, int type, 121e1051a39Sopenharmony_ci const void *bytes, int len) 122e1051a39Sopenharmony_ci{ 123e1051a39Sopenharmony_ci if (X509at_add1_attr_by_txt(&si->signedAttrs, attrname, type, bytes, len)) 124e1051a39Sopenharmony_ci return 1; 125e1051a39Sopenharmony_ci return 0; 126e1051a39Sopenharmony_ci} 127e1051a39Sopenharmony_ci 128e1051a39Sopenharmony_civoid *CMS_signed_get0_data_by_OBJ(const CMS_SignerInfo *si, 129e1051a39Sopenharmony_ci const ASN1_OBJECT *oid, 130e1051a39Sopenharmony_ci int lastpos, int type) 131e1051a39Sopenharmony_ci{ 132e1051a39Sopenharmony_ci return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type); 133e1051a39Sopenharmony_ci} 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ciint CMS_unsigned_get_attr_count(const CMS_SignerInfo *si) 136e1051a39Sopenharmony_ci{ 137e1051a39Sopenharmony_ci return X509at_get_attr_count(si->unsignedAttrs); 138e1051a39Sopenharmony_ci} 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ciint CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, 141e1051a39Sopenharmony_ci int lastpos) 142e1051a39Sopenharmony_ci{ 143e1051a39Sopenharmony_ci return X509at_get_attr_by_NID(si->unsignedAttrs, nid, lastpos); 144e1051a39Sopenharmony_ci} 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ciint CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, 147e1051a39Sopenharmony_ci const ASN1_OBJECT *obj, int lastpos) 148e1051a39Sopenharmony_ci{ 149e1051a39Sopenharmony_ci return X509at_get_attr_by_OBJ(si->unsignedAttrs, obj, lastpos); 150e1051a39Sopenharmony_ci} 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ciX509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci return X509at_get_attr(si->unsignedAttrs, loc); 155e1051a39Sopenharmony_ci} 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ciX509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc) 158e1051a39Sopenharmony_ci{ 159e1051a39Sopenharmony_ci return X509at_delete_attr(si->unsignedAttrs, loc); 160e1051a39Sopenharmony_ci} 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ciint CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr) 163e1051a39Sopenharmony_ci{ 164e1051a39Sopenharmony_ci if (X509at_add1_attr(&si->unsignedAttrs, attr)) 165e1051a39Sopenharmony_ci return 1; 166e1051a39Sopenharmony_ci return 0; 167e1051a39Sopenharmony_ci} 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_ciint CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, 170e1051a39Sopenharmony_ci const ASN1_OBJECT *obj, int type, 171e1051a39Sopenharmony_ci const void *bytes, int len) 172e1051a39Sopenharmony_ci{ 173e1051a39Sopenharmony_ci if (X509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj, type, bytes, len)) 174e1051a39Sopenharmony_ci return 1; 175e1051a39Sopenharmony_ci return 0; 176e1051a39Sopenharmony_ci} 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ciint CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, 179e1051a39Sopenharmony_ci int nid, int type, 180e1051a39Sopenharmony_ci const void *bytes, int len) 181e1051a39Sopenharmony_ci{ 182e1051a39Sopenharmony_ci if (X509at_add1_attr_by_NID(&si->unsignedAttrs, nid, type, bytes, len)) 183e1051a39Sopenharmony_ci return 1; 184e1051a39Sopenharmony_ci return 0; 185e1051a39Sopenharmony_ci} 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ciint CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, 188e1051a39Sopenharmony_ci const char *attrname, int type, 189e1051a39Sopenharmony_ci const void *bytes, int len) 190e1051a39Sopenharmony_ci{ 191e1051a39Sopenharmony_ci if (X509at_add1_attr_by_txt(&si->unsignedAttrs, attrname, 192e1051a39Sopenharmony_ci type, bytes, len)) 193e1051a39Sopenharmony_ci return 1; 194e1051a39Sopenharmony_ci return 0; 195e1051a39Sopenharmony_ci} 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_civoid *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, 198e1051a39Sopenharmony_ci int lastpos, int type) 199e1051a39Sopenharmony_ci{ 200e1051a39Sopenharmony_ci return X509at_get0_data_by_OBJ(si->unsignedAttrs, oid, lastpos, type); 201e1051a39Sopenharmony_ci} 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci/* 204e1051a39Sopenharmony_ci * Retrieve an attribute by nid from a stack of attributes starting at index 205e1051a39Sopenharmony_ci * *lastpos + 1. 206e1051a39Sopenharmony_ci * Returns the attribute or NULL if there is no attribute. 207e1051a39Sopenharmony_ci * If an attribute was found *lastpos returns the index of the found attribute. 208e1051a39Sopenharmony_ci */ 209e1051a39Sopenharmony_cistatic X509_ATTRIBUTE *cms_attrib_get(int nid, 210e1051a39Sopenharmony_ci const STACK_OF(X509_ATTRIBUTE) *attrs, 211e1051a39Sopenharmony_ci int *lastpos) 212e1051a39Sopenharmony_ci{ 213e1051a39Sopenharmony_ci X509_ATTRIBUTE *at; 214e1051a39Sopenharmony_ci int loc; 215e1051a39Sopenharmony_ci 216e1051a39Sopenharmony_ci loc = X509at_get_attr_by_NID(attrs, nid, *lastpos); 217e1051a39Sopenharmony_ci if (loc < 0) 218e1051a39Sopenharmony_ci return NULL; 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_ci at = X509at_get_attr(attrs, loc); 221e1051a39Sopenharmony_ci *lastpos = loc; 222e1051a39Sopenharmony_ci return at; 223e1051a39Sopenharmony_ci} 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_cistatic int cms_check_attribute(int nid, int flags, int type, 226e1051a39Sopenharmony_ci const STACK_OF(X509_ATTRIBUTE) *attrs, 227e1051a39Sopenharmony_ci int have_attrs) 228e1051a39Sopenharmony_ci{ 229e1051a39Sopenharmony_ci int lastpos = -1; 230e1051a39Sopenharmony_ci X509_ATTRIBUTE *at = cms_attrib_get(nid, attrs, &lastpos); 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci if (at != NULL) { 233e1051a39Sopenharmony_ci int count = X509_ATTRIBUTE_count(at); 234e1051a39Sopenharmony_ci 235e1051a39Sopenharmony_ci /* Is this attribute allowed? */ 236e1051a39Sopenharmony_ci if (((flags & type) == 0) 237e1051a39Sopenharmony_ci /* check if multiple attributes of the same type are allowed */ 238e1051a39Sopenharmony_ci || (((flags & CMS_ATTR_F_ONLY_ONE) != 0) 239e1051a39Sopenharmony_ci && cms_attrib_get(nid, attrs, &lastpos) != NULL) 240e1051a39Sopenharmony_ci /* Check if attribute should have exactly one value in its set */ 241e1051a39Sopenharmony_ci || (((flags & CMS_ATTR_F_ONE_ATTR_VALUE) != 0) 242e1051a39Sopenharmony_ci && count != 1) 243e1051a39Sopenharmony_ci /* There should be at least one value */ 244e1051a39Sopenharmony_ci || count == 0) 245e1051a39Sopenharmony_ci return 0; 246e1051a39Sopenharmony_ci } else { 247e1051a39Sopenharmony_ci /* fail if a required attribute is missing */ 248e1051a39Sopenharmony_ci if (have_attrs 249e1051a39Sopenharmony_ci && ((flags & CMS_ATTR_F_REQUIRED_COND) != 0) 250e1051a39Sopenharmony_ci && (flags & type) != 0) 251e1051a39Sopenharmony_ci return 0; 252e1051a39Sopenharmony_ci } 253e1051a39Sopenharmony_ci return 1; 254e1051a39Sopenharmony_ci} 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci/* 257e1051a39Sopenharmony_ci * Check that the signerinfo attributes obey the attribute rules which includes 258e1051a39Sopenharmony_ci * the following checks 259e1051a39Sopenharmony_ci * - If any signed attributes exist then there must be a Content Type 260e1051a39Sopenharmony_ci * and Message Digest attribute in the signed attributes. 261e1051a39Sopenharmony_ci * - The countersignature attribute is an optional unsigned attribute only. 262e1051a39Sopenharmony_ci * - Content Type, Message Digest, and Signing time attributes are signed 263e1051a39Sopenharmony_ci * attributes. Only one instance of each is allowed, with each of these 264e1051a39Sopenharmony_ci * attributes containing a single attribute value in its set. 265e1051a39Sopenharmony_ci */ 266e1051a39Sopenharmony_ciint ossl_cms_si_check_attributes(const CMS_SignerInfo *si) 267e1051a39Sopenharmony_ci{ 268e1051a39Sopenharmony_ci int i; 269e1051a39Sopenharmony_ci int have_signed_attrs = (CMS_signed_get_attr_count(si) > 0); 270e1051a39Sopenharmony_ci int have_unsigned_attrs = (CMS_unsigned_get_attr_count(si) > 0); 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci for (i = 0; i < (int)OSSL_NELEM(cms_attribute_properties); ++i) { 273e1051a39Sopenharmony_ci int nid = cms_attribute_properties[i].nid; 274e1051a39Sopenharmony_ci int flags = cms_attribute_properties[i].flags; 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci if (!cms_check_attribute(nid, flags, CMS_ATTR_F_SIGNED, 277e1051a39Sopenharmony_ci si->signedAttrs, have_signed_attrs) 278e1051a39Sopenharmony_ci || !cms_check_attribute(nid, flags, CMS_ATTR_F_UNSIGNED, 279e1051a39Sopenharmony_ci si->unsignedAttrs, have_unsigned_attrs)) { 280e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_ATTRIBUTE_ERROR); 281e1051a39Sopenharmony_ci return 0; 282e1051a39Sopenharmony_ci } 283e1051a39Sopenharmony_ci } 284e1051a39Sopenharmony_ci return 1; 285e1051a39Sopenharmony_ci} 286