1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "signer_info.h" 17 18#include <openssl/asn1.h> 19#include <openssl/pem.h> 20#include <openssl/obj_mac.h> 21#include <openssl/pkcs7.h> 22#include <openssl/x509.h> 23#include <openssl/objects.h> 24#include <securec.h> 25 26#include "errcode.h" 27#include "log.h" 28#include "openssl_utils.h" 29 30namespace OHOS { 31namespace Security { 32namespace CodeSign { 33static constexpr int INVALID_SIGN_ALGORITHM_NID = -1; 34static constexpr int MAX_SIGNATURE_SIZE = 1024; // 1024: max signature length 35 36// OID used for code signing to mark owner ID 37const std::string SignerInfo::OWNERID_OID = "1.3.6.1.4.1.2011.2.376.1.4.1"; 38const std::string SignerInfo::OWNERID_OID_SHORT_NAME = "ownerID"; 39const std::string SignerInfo::OWNERID_OID_LONG_NAME = "Code Signature Owner ID"; 40 41bool SignerInfo::InitSignerInfo(const std::string &ownerID, X509 *cert, const EVP_MD *md, 42 const ByteBuffer &contentData, bool carrySigningTime) 43{ 44 if ((cert == nullptr) || (md == nullptr)) { 45 return false; 46 } 47 md_ = md; 48 carrySigningTime_ = carrySigningTime; 49 p7info_ = PKCS7_SIGNER_INFO_new(); 50 if (p7info_ == nullptr) { 51 ERR_LOG_WITH_OPEN_SSL_MSG("Create pkcs7 signer info failed"); 52 return false; 53 } 54 bool ret = false; 55 do { 56 // set default information, pkcs7 signer info version is 1 57 if (!ASN1_INTEGER_set(p7info_->version, 1)) { 58 break; 59 } 60 61 // add sign cert info 62 if (!X509_NAME_set(&p7info_->issuer_and_serial->issuer, 63 X509_get_issuer_name(cert))) { 64 break; 65 } 66 ASN1_INTEGER_free(p7info_->issuer_and_serial->serial); 67 if (!(p7info_->issuer_and_serial->serial = 68 ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) { 69 break; 70 } 71 72 // add digest and signature algorithm 73 if (!X509_ALGOR_set0(p7info_->digest_alg, OBJ_nid2obj(EVP_MD_type(md)), 74 V_ASN1_NULL, nullptr)) { 75 break; 76 } 77 int signatureNid = GetSignAlgorithmID(cert); 78 if (signatureNid < 0) { 79 break; 80 } 81 if (!X509_ALGOR_set0(p7info_->digest_enc_alg, OBJ_nid2obj(signatureNid), 82 V_ASN1_NULL, nullptr)) { 83 break; 84 } 85 86 if (!AddAttrsToSignerInfo(ownerID, contentData)) { 87 ERR_LOG_WITH_OPEN_SSL_MSG("Add attributes to signer info failed"); 88 break; 89 } 90 ret = true; 91 } while (0); 92 if (!ret) { 93 PKCS7_SIGNER_INFO_free(p7info_); 94 ERR_LOG_WITH_OPEN_SSL_MSG("Init pkcs7 signer info failed"); 95 } 96 return ret; 97} 98 99bool SignerInfo::AddAttrsToSignerInfo(const std::string &ownerID, const ByteBuffer &contentData) 100{ 101 if (!carrySigningTime_ && ownerID.empty()) { 102 unsignedData_ = std::make_unique<ByteBuffer>(); 103 if (!unsignedData_->CopyFrom(contentData.GetBuffer(), contentData.GetSize())) { 104 unsignedData_.reset(nullptr); 105 return false; 106 } 107 return true; 108 } 109 110 if (!ownerID.empty()) { 111 AddOwnerID(ownerID); 112 } 113 114 if (!PKCS7_add_attrib_content_type(p7info_, nullptr)) { 115 return false; 116 } 117 118 if (carrySigningTime_) { 119 if (!PKCS7_add0_attrib_signing_time(p7info_, nullptr)) { 120 return false; 121 } 122 } 123 124 ByteBuffer digest; 125 if (!ComputeDigest(contentData, digest)) { 126 return false; 127 } 128 if (!PKCS7_add1_attrib_digest(p7info_, digest.GetBuffer(), digest.GetSize())) { 129 ERR_LOG_WITH_OPEN_SSL_MSG("PKCS7_add1_attrib_digest fail"); 130 return false; 131 } 132 return true; 133} 134 135uint8_t *SignerInfo::GetDataToSign(uint32_t &len) 136{ 137 if (p7info_ == nullptr) { 138 return nullptr; 139 } 140 141 uint8_t *data = nullptr; 142 if (p7info_->auth_attr != nullptr) { 143 int itemLen = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE *>(p7info_->auth_attr), &data, 144 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 145 if (itemLen < 0) { 146 return nullptr; 147 } 148 len = static_cast<uint32_t>(itemLen); 149 } else { 150 if (unsignedData_ == nullptr) { 151 return nullptr; 152 } 153 data = unsignedData_->GetBuffer(); 154 len = unsignedData_->GetSize(); 155 } 156 return data; 157} 158 159bool SignerInfo::AddSignatureInSignerInfo(const ByteBuffer &signature) 160{ 161 if (p7info_ == nullptr) { 162 return false; 163 } 164 uint32_t signatureSize = signature.GetSize(); 165 // tmp will be free when freeing p7info_ 166 if (signatureSize == 0 || signatureSize > MAX_SIGNATURE_SIZE) { 167 return false; 168 } 169 uint8_t *tmp = static_cast<uint8_t *>(malloc(signatureSize)); 170 if (tmp == nullptr) { 171 return false; 172 } 173 (void)memcpy_s(tmp, signatureSize, signature.GetBuffer(), signatureSize); 174 ASN1_STRING_set0(p7info_->enc_digest, tmp, signatureSize); 175 return true; 176} 177 178bool SignerInfo::ComputeDigest(const ByteBuffer &data, ByteBuffer &digest) 179{ 180 uint8_t mdBuffer[EVP_MAX_MD_SIZE]; 181 uint32_t mdLen = 0; 182 EVP_MD_CTX *mCtx = EVP_MD_CTX_new(); 183 bool ret = false; 184 do { 185 if (mCtx == nullptr) { 186 break; 187 } 188 if (!EVP_DigestInit_ex(mCtx, md_, nullptr)) { 189 break; 190 } 191 if (!EVP_DigestUpdate(mCtx, data.GetBuffer(), data.GetSize())) { 192 break; 193 } 194 if (!EVP_DigestFinal_ex(mCtx, mdBuffer, &mdLen)) { 195 break; 196 } 197 ret = true; 198 } while (0); 199 if (!ret) { 200 ERR_LOG_WITH_OPEN_SSL_MSG("Compute digest failed."); 201 } else if (!digest.CopyFrom(mdBuffer, mdLen)) { 202 ret = false; 203 } 204 EVP_MD_CTX_free(mCtx); 205 return ret; 206} 207 208int SignerInfo::GetSignAlgorithmID(const X509 *cert) 209{ 210 X509_PUBKEY *xpkey = X509_get_X509_PUBKEY(cert); 211 ASN1_OBJECT *koid = nullptr; 212 if (!X509_PUBKEY_get0_param(&koid, nullptr, nullptr, nullptr, xpkey)) { 213 return INVALID_SIGN_ALGORITHM_NID; 214 } 215 int signatureNid = OBJ_obj2nid(koid); 216 if (signatureNid == NID_rsaEncryption) { 217 return signatureNid; 218 } 219 OBJ_find_sigid_by_algs(&signatureNid, EVP_MD_type(md_), signatureNid); 220 return signatureNid; 221} 222 223PKCS7_SIGNER_INFO *SignerInfo::GetSignerInfo() 224{ 225 return p7info_; 226} 227 228int SignerInfo::AddOwnerID(const std::string &ownerID) 229{ 230 int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME); 231 ASN1_STRING *ownerIDAsn1 = ASN1_STRING_new(); 232 ASN1_STRING_set(ownerIDAsn1, ownerID.c_str(), ownerID.length()); 233 int ret = PKCS7_add_signed_attribute(p7info_, nid, V_ASN1_UTF8STRING, ownerIDAsn1); 234 if (ret == 0) { 235 ASN1_STRING_free(ownerIDAsn1); 236 ERR_LOG_WITH_OPEN_SSL_MSG("PKCS7_add_signed_attribute failed"); 237 return CS_ERR_OPENSSL_PKCS7; 238 } 239 240 return CS_SUCCESS; 241} 242 243int SignerInfo::ParseOwnerIdFromSignature(const ByteBuffer &sigbuffer, std::string &ownerID) 244{ 245 int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME); 246 BIO *bio = BIO_new_mem_buf(sigbuffer.GetBuffer(), sigbuffer.GetSize()); 247 if (bio == nullptr) { 248 ERR_LOG_WITH_OPEN_SSL_MSG("BIO_new_mem_buf failed"); 249 return CS_ERR_OPENSSL_BIO; 250 } 251 PKCS7 *p7 = d2i_PKCS7_bio(bio, nullptr); 252 if (p7 == nullptr) { 253 BIO_free(bio); 254 ERR_LOG_WITH_OPEN_SSL_MSG("d2i_PKCS7_bio failed"); 255 return CS_ERR_OPENSSL_PKCS7; 256 } 257 258 STACK_OF(PKCS7_SIGNER_INFO) *signerInfosk = PKCS7_get_signer_info(p7); 259 if (signerInfosk == nullptr) { 260 BIO_free(bio); 261 PKCS7_free(p7); 262 ERR_LOG_WITH_OPEN_SSL_MSG("PKCS7_get_signer_info failed"); 263 return CS_ERR_OPENSSL_PKCS7; 264 } 265 for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(signerInfosk); i++) { 266 PKCS7_SIGNER_INFO *signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfosk, i); 267 ASN1_TYPE *asn1Type = PKCS7_get_signed_attribute(signerInfo, nid); 268 if (asn1Type != nullptr && asn1Type->type == V_ASN1_UTF8STRING) { 269 ASN1_STRING *result = asn1Type->value.asn1_string; 270 ownerID.assign(reinterpret_cast<const char *>(ASN1_STRING_get0_data(result)), ASN1_STRING_length(result)); 271 break; 272 } 273 } 274 BIO_free(bio); 275 PKCS7_free(p7); 276 if (ownerID.empty()) { 277 return CS_ERR_NO_OWNER_ID; 278 } 279 return CS_SUCCESS; 280} 281} 282} 283} 284