You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
int32_tgen_sig_data_cms(constchar*in_file,
constchar*cert_file,
constchar*key_file,
constchar*sig_out_name,
hash_alg_thash_alg,
uint8_t*sig_buf,
size_t*sig_buf_bytes)
{
BIO*bio_in=NULL; /**< BIO for in_file data */X509*cert=NULL; /**< Ptr to X509 certificate read data */EVP_PKEY*key=NULL; /**< Ptr to key read data */CMS_ContentInfo*cms=NULL; /**< Ptr used with openssl API */constEVP_MD*sign_md=NULL; /**< Ptr to digest name */int32_terr_value=CAL_SUCCESS; /**< Used for return value *//** Array to hold error string */charerr_str[MAX_ERR_STR_BYTES];
/* flags set to match Openssl command line options for generating * signatures */int32_tflags=CMS_DETACHED | CMS_NOCERTS |
CMS_NOSMIMECAP | CMS_BINARY;
if (NULL==in_file||NULL==cert_file||NULL==key_file||NULL==sig_out_name||NULL==sig_buf||NULL==sig_buf_bytes||hash_alg >= INVALID_DIGEST) {
display_error("Input param error!\n");
returnCAL_INVALID_ARGUMENT;
}
/* Set signature message digest alg */sign_md=EVP_get_digestbyname(get_digest_name(hash_alg));
if (sign_md==NULL) {
display_error("Invalid hash digest algorithm");
returnCAL_INVALID_ARGUMENT;
}
do
{
cert=read_certificate(cert_file);
if (!cert) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open certificate file %s", cert_file);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Read key */key=read_private_key(key_file,
(pem_password_cb*)get_passcode_to_key_file,
key_file);
if (!key) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open key file %s", key_file);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Read Data to be signed */if (!(bio_in=BIO_new_file(in_file, "rb"))) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open data file %s", in_file);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Generate CMS Signature - can only use CMS_sign if default * MD is used which is SHA1 */flags |= CMS_PARTIAL;
cms=CMS_sign(NULL, NULL, NULL, bio_in, flags);
if (!cms) {
display_error("Failed to initialize CMS signature");
err_value=CAL_CRYPTO_API_ERROR;
break;
}
if (!CMS_add1_signer(cms, cert, key, sign_md, flags)) {
display_error("Failed to generate CMS signature");
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Finalize the signature */if (!CMS_final(cms, bio_in, NULL, flags)) {
display_error("Failed to finalize CMS signature");
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Write CMS signature to output buffer - DER format */err_value=cms_to_buf(cms, bio_in, sig_buf, sig_buf_bytes, flags);
} while(0);
do {
BIO*yy=BIO_new_file(sig_out_name, "wb");
BIO_write(yy, sig_buf, *sig_buf_bytes);
BIO_free(yy);
} while (0);
/* Print any Openssl errors */if (err_value!=CAL_SUCCESS) {
ERR_print_errors_fp(stderr);
}
/* Close everything down */if (cms) CMS_ContentInfo_free(cms);
if (cert) X509_free(cert);
if (key) EVP_PKEY_free(key);
if (bio_in) BIO_free(bio_in);
returnerr_value;
}
int32_tverify_sig_data_cms(constchar*in_file,
constchar*cert_ca,
constchar*cert_signer,
constchar*sig_file,
hash_alg_thash_alg)
{
BIO*bio_in=NULL; /**< BIO for in_file data */BIO*bio_sigfile=NULL; /**< BIO for sigfile data */X509_STORE*store=NULL; /**< Ptr to X509 certificate read data */X509*signer_cert=NULL;
CMS_ContentInfo*cms=NULL; /**< Ptr used with openssl API */constEVP_MD*sign_md=NULL; /**< Ptr to digest name */int32_terr_value=CAL_SUCCESS; /**< Used for return value */int32_trc=0;
/** Array to hold error string */charerr_str[MAX_ERR_STR_BYTES];
/* flags set to match Openssl command line options for generating * signatures */int32_tflags=CMS_DETACHED | CMS_NOCERTS |
CMS_NOSMIMECAP | CMS_BINARY;
if (NULL==in_file||NULL==cert_ca||NULL==cert_signer||NULL==sig_file||hash_alg >= INVALID_DIGEST) {
display_error("Input param error!\n");
returnCAL_INVALID_ARGUMENT;
}
/* Set signature message digest alg */sign_md=EVP_get_digestbyname(get_digest_name(hash_alg));
if (sign_md==NULL) {
display_error("Invalid hash digest algorithm");
returnCAL_INVALID_ARGUMENT;
}
do
{
store=load_cert_chain(cert_ca);
if (store==NULL) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open certificates file %s", cert_ca);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
signer_cert=read_certificate(cert_signer);
if (!signer_cert) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open certificate file %s", cert_signer);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Read signature Data */if (!(bio_sigfile=BIO_new_file(sig_file, "rb"))) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open signature file %s", sig_file);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
flags |= CMS_NO_SIGNER_CERT_VERIFY;
/* Parse the DER-encoded CMS message */cms=d2i_CMS_bio(bio_sigfile, NULL);
if (!cms) {
display_error("Cannot be parsed as DER-encoded CMS signature blob.\n");
err_value=CAL_CRYPTO_API_ERROR;
break;
}
if (!CMS_add1_cert(cms, signer_cert)) {
display_error("Cannot be inserted signer_cert into cms.\n");
err_value=CAL_CRYPTO_API_ERROR;
break;
}
/* Open the content file (data which was signed) */if (!(bio_in=BIO_new_file(in_file, "rb"))) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Cannot open data which was signed %s", in_file);
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
rc=CMS_verify(cms, NULL, store, bio_in, NULL, flags);
if (!rc) {
display_error("Failed to verify the file!\n");
err_value=CAL_CRYPTO_API_ERROR;
break;
}
if (check_verified_signer(cms, store)) {
snprintf(err_str, MAX_ERR_STR_BYTES-1,
"Authentication of all signatures failed!\n");
display_error(err_str);
err_value=CAL_CRYPTO_API_ERROR;
break;
}
LOG_DEBUG("Verified OK!\n");
} while(0);
/* Print any Openssl errors */if (err_value!=CAL_SUCCESS) {
ERR_print_errors_fp(stderr);
}
/* Close everything down */if (cms) CMS_ContentInfo_free(cms);
if (store) X509_STORE_free(store);
if (bio_in) BIO_free(bio_in);
if (bio_sigfile) BIO_free(bio_sigfile);
returnerr_value;
The text was updated successfully, but these errors were encountered:
在NXP High Assurance Booting (HAB)中,整体的RSA认证体系全部使用的PKCS7中CMS签名Cryptographic Message Syntax (CMS),借此机会,对CMS签名认证相关的专业知识进行整理。PKCS#7是一个复杂的格式,也叫做CMS。
Cryptographic Message Syntax (CMS)是IETF密码学标准用于保护消息。用于数字签名、digest、认证或者加密。CMS基于PKCS#7的原语,基于Privacy-Enhanced Mail standard,最新的CMS版本是2009。CMS架构的建立是基于certificate-based证书的key的管理,其中也使用S/MIME、PKCS#12、还有RFC3161时间戳协议。OpenSSL对于CMS进行了完整的实现。
签名格式
一个CMS的签名的信息主要包含两部分,其一是数字签名本身(加密了的hash值),其二就是signer的信息。数字签名本身没有什么好介绍的,和一般的RSA签名一致,而signer信息就很丰富了。
Signer信息包含:
一个典型的CMS签过的二进制数据如下面图所示:
(未突出显示的部分(黑色)是ASN.1说明符和其他属性、算法等)
这个图中的signed message包含原始签名的content和signer的证书,但是没有一些认证的属性。签名的数据块被RSA的private key联合signer的证书加密。
除了典型的CMS二进制数据格式,还有一个比较简单的用例:
(未突出显示的部分(黑色)是ASN.1说明符和其他属性、算法等)
如果做认证的属性(例如:时间戳)也包含进入CMS signed file,那么signature最后的hash值中也把这个属性信息包含进去了。
参考:https://www.jensign.com/sigview/index.html
PKI机制
自签Key和cert
CMS使用PKI机制,因此需要一个CA机制,可以按照:
生成过程:
虚构一个CA认证机构出来:
生成Sign Server的证书:
用上面那个虚构出来的CA机构来认证:
使用CA对CSR进行签名,得到server.crt
至此,私钥
server.key
和证书server.crt
已全部生成完毕。我们可以通过openssl的verify功能验证server.crt是否是ca.key签出来的:
CMS签名和认证
签名
验签
在CMS签名文件Blob中包含:
在CMS Blob中有了signserver的公钥信息,因此在验签的时候不需要指定certfile;而blob中也包含原始的签名内容,因此也不需要指定content内容。
参考: https://blog.csdn.net/as3luyuan123/article/details/13612917?ydreferer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8%3D
多级证书
应用中常常需要CA签发多级证书,例如下图的应用场景。在PKI验签中,此时指定的证书需要,把证书链存入一个cert store中,然后有了store之后一级一级的对证书进行验证。
制作一个验证证书的脚本,对证书链进行验证:
调用
bash ./verify_chains.sh CA1_sha256_2048_65537_v3_ca_crt.pem SRK1_sha256_2048_65537_v3_ca_crt.pem IMG1_1_sha256_2048_65537_v3_usr_crt.pem
这样就验证了最底层IMG1_1_sha256_2048_65537_v3_usr_crt的合法性。
这个脚本中生成
tmpca.cer
是一个包含CA证书的证书链。在验证多级证书签名的数据要使用下面的方法:参考: https://blog.csdn.net/xiangguiwang/article/details/80336755
openssl c语言 示例
下面我们使用openssl的C语言接口对数据进行sign和verify,我这里已经包装成了工具 https://github.com/carloscn/cryptography/tree/master/tools/cms_sign_verify_tool
sign过程
https://github.com/carloscn/cryptography/blob/master/tools/cms_sign_verify_tool/cms_tool.c#L532
传入安全相关的参数:
make sign
可以一键测试sign的功能sign之后的二进制信息可以用openssl来查看:
openssl pkcs7 -inform der -in sign.out -print
verify 过程
https://github.com/carloscn/cryptography/blob/master/tools/cms_sign_verify_tool/cms_tool.c#L302
verify输入的安全相关参数:
The text was updated successfully, but these errors were encountered: