Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder(MessageDigest::Algorithm mesDigAlgorithm, Certificate &cert, PrivateKey &privKey, bool attached) throw (Pkcs7Exception) { int rc; PKCS7_SIGNER_INFO *si; PKCS7_set_type(this->pkcs7, NID_pkcs7_signed); PKCS7_content_new(this->pkcs7, NID_pkcs7_data); if (!attached) { PKCS7_set_detached(this->pkcs7, 1); } si = PKCS7_add_signature(this->pkcs7, cert.getX509(), privKey.getEvpPkey(), MessageDigest::getMessageDigest(mesDigAlgorithm)); if (!si) { PKCS7_free(this->pkcs7); this->pkcs7 = NULL; throw Pkcs7Exception(Pkcs7Exception::ADDING_SIGNER, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true); } rc = PKCS7_add_certificate(this->pkcs7, cert.getX509()); if (!rc) { PKCS7_free(this->pkcs7); this->pkcs7 = NULL; throw Pkcs7Exception(Pkcs7Exception::ADDING_CERTIFICATE, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true); } this->state = Pkcs7Builder::INIT; }
static VALUE ossl_pkcs7_set_detached(VALUE self, VALUE flag) { PKCS7 *p7; GetPKCS7(self, p7); if(flag != Qtrue && flag != Qfalse) ossl_raise(ePKCS7Error, "must specify a boolean"); if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0)) ossl_raise(ePKCS7Error, NULL); return flag; }
void Pkcs7SignedDataBuilder::init(MessageDigest::Algorithm mesDigAlgorithm, Certificate &cert, PrivateKey &privKey, bool attached) throw (Pkcs7Exception) { int rc; if (this->state != Pkcs7Builder::NO_INIT) { PKCS7_free(this->pkcs7); this->pkcs7 = NULL; if (this->state == Pkcs7Builder::UPDATE) { BIO_free(this->p7bio); this->p7bio = NULL; } } this->pkcs7 = PKCS7_new(); PKCS7_set_type(this->pkcs7, NID_pkcs7_signed); if (!attached) { PKCS7_set_detached(this->pkcs7, 1); } if (!PKCS7_add_signature(this->pkcs7, cert.getX509(), privKey.getEvpPkey(), MessageDigest::getMessageDigest(mesDigAlgorithm))) { PKCS7_free(this->pkcs7); this->pkcs7 = NULL; throw Pkcs7Exception(Pkcs7Exception::ADDING_SIGNER, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true); } rc = PKCS7_add_certificate(this->pkcs7, cert.getX509()); if (!rc)//inversor adicionado (martin 28/11/07) { PKCS7_free(this->pkcs7); this->pkcs7 = NULL; throw Pkcs7Exception(Pkcs7Exception::ADDING_CERTIFICATE, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true); } this->state = Pkcs7Builder::INIT; }
/* will return 0, 1, 3, or 99 */ static int _pkgtrans(char *device1, char *device2, char **pkg, int options, keystore_handle_t keystore, char *keystore_alias) { BIO *p7_bio = NULL; EVP_PKEY *privkey = NULL; PKCS7 *sec_pkcs7 = NULL; PKCS7_SIGNER_INFO *sec_signerinfo = NULL; PKG_ERR *err; STACK_OF(X509) *cacerts = NULL; STACK_OF(X509) *clcerts = NULL; STACK_OF(X509) *sec_chain = NULL; X509 *pubcert = NULL; boolean_t making_sig = B_FALSE; char *src, *dst; int errflg, i, n; struct dm_buf *hdr; making_sig = (keystore != NULL) ? B_TRUE : B_FALSE; if (making_sig) { /* new error object */ err = pkgerr_new(); /* find matching cert and key */ if (find_key_cert_pair(err, keystore, keystore_alias, &privkey, &pubcert) != 0) { pkgerr(err); pkgerr_free(err); return (1); } /* get CA certificates */ if (find_ca_certs(err, keystore, &cacerts) != 0) { pkgerr(err); pkgerr_free(err); return (1); } /* get CL (aka "chain") certificates */ if (find_cl_certs(err, keystore, &clcerts) != 0) { pkgerr(err); pkgerr_free(err); return (1); } /* initialize PKCS7 object to be filled in later */ sec_pkcs7 = PKCS7_new(); (void) PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed); sec_signerinfo = PKCS7_add_signature(sec_pkcs7, pubcert, privkey, EVP_sha1()); if (sec_signerinfo == NULL) { progerr(gettext(ERR_SEC), keystore_alias); ERR_print_errors_fp(stderr); pkgerr_free(err); return (1); } /* add signer cert into signature */ (void) PKCS7_add_certificate(sec_pkcs7, pubcert); /* attempt to resolve cert chain starting at the signer cert */ if (get_cert_chain(err, pubcert, clcerts, cacerts, &sec_chain) != 0) { pkgerr(err); pkgerr_free(err); return (1); } /* * add the verification chain of certs into the signature. * The first cert is the user cert, which we don't need, * since it's baked in already, so skip it */ for (i = 1; i < sk_X509_num(sec_chain); i++) { (void) PKCS7_add_certificate(sec_pkcs7, sk_X509_value(sec_chain, i)); } pkgerr_free(err); err = NULL; } if (signal_received > 0) { return (1); } /* transfer spool to appropriate device */ if (devtype(device1, &srcdev)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_BADDEV), device1); return (1); } srcdev.rdonly++; /* check for datastream */ ids_name = NULL; if (srcdev.bdevice) { if (n = _getvol(srcdev.bdevice, NULL, NULL, pkg_gt("Insert %v into %p."), srcdev.norewind)) { cleanup(); if (n == 3) return (3); progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_GETVOL)); return (1); } if (ds_readbuf(srcdev.cdevice)) ids_name = srcdev.cdevice; } if (srcdev.cdevice && !srcdev.bdevice) ids_name = srcdev.cdevice; else if (srcdev.pathname) { ids_name = srcdev.pathname; if (access(ids_name, 0) == -1) { progerr(ERR_TRANSFER); logerr(pkg_gt(MSG_GETVOL)); return (1); } } if (!ids_name && device2 == (char *)0) { if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) { cleanup(); return (n); } if (srcdev.mount && *srcdev.mount) pkgdir = strdup(srcdev.mount); return (0); } if (ids_name && device2 == (char *)0) { tmppath = tmpnam(NULL); tmppath = strdup(tmppath); if (tmppath == NULL) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_MEM)); return (1); } if (mkdir(tmppath, 0755)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_MKDIR), tmppath); return (1); } device2 = tmppath; } if (devtype(device2, &dstdev)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_BADDEV), device2); return (1); } if ((srcdev.cdevice && dstdev.cdevice) && strcmp(srcdev.cdevice, dstdev.cdevice) == 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_SAMEDEV)); return (1); } ods_name = NULL; if (dstdev.cdevice && !dstdev.bdevice || dstdev.pathname) options |= PT_ODTSTREAM; if (options & PT_ODTSTREAM) { if (!((ods_name = dstdev.cdevice) != NULL || (ods_name = dstdev.pathname) != NULL)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_BADDEV), device2); return (1); } if (ids_name) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_TWODSTREAM)); return (1); } } else { /* * output device isn't a stream. If we're making a signed * package, then fail, since we can't make signed, * non-stream pkgs */ if (making_sig) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(ERR_CANTSIGN)); return (1); } } if ((srcdev.dirname && dstdev.dirname) && strcmp(srcdev.dirname, dstdev.dirname) == 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_SAMEDEV)); return (1); } if ((srcdev.pathname && dstdev.pathname) && strcmp(srcdev.pathname, dstdev.pathname) == 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_SAMEDEV)); return (1); } if (signal_received > 0) { return (1); } if (ids_name) { if (srcdev.cdevice && !srcdev.bdevice && (n = _getvol(srcdev.cdevice, NULL, NULL, NULL, srcdev.norewind))) { cleanup(); if (n == 3) return (3); progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_GETVOL)); return (1); } if (srcdev.dirname = tmpnam(NULL)) tmpdir = srcdev.dirname = strdup(srcdev.dirname); if ((srcdev.dirname == NULL) || mkdir(srcdev.dirname, 0755) || chdir(srcdev.dirname)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_NOTEMP), srcdev.dirname); cleanup(); return (1); } if (ds_init(ids_name, pkg, srcdev.norewind)) { cleanup(); return (1); } } else if (srcdev.mount) { if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) { cleanup(); return (n); } } src = srcdev.dirname; dst = dstdev.dirname; if (chdir(src)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CHDIR), src); cleanup(); return (1); } if (signal_received > 0) { return (1); } xpkg = pkg = gpkglist(src, pkg, NULL); if (!pkg) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_NOPKGS), src); cleanup(); return (1); } for (nxpkg = 0; pkg[nxpkg]; /* void */) { nxpkg++; /* count */ } if (ids_name) { ds_order(pkg); /* order requests */ } if (signal_received > 0) { return (1); } if (options & PT_ODTSTREAM) { char line[128]; if (!dstdev.pathname && (n = _getvol(ods_name, NULL, DM_FORMAT, NULL, dstdev.norewind))) { cleanup(); if (n == 3) return (3); progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_GETVOL)); return (1); } if ((hdr = genheader(src, pkg)) == NULL) { cleanup(); return (1); } if (making_sig) { /* start up signature data stream */ (void) PKCS7_content_new(sec_pkcs7, NID_pkcs7_data); (void) PKCS7_set_detached(sec_pkcs7, 1); p7_bio = PKCS7_dataInit(sec_pkcs7, NULL); /* * Here we generate all the data that will go into * the package, and send it through the signature * generator, essentially calculating the signature * of the entire package so we can place it in the * header. Otherwise we'd have to place it at the end * of the pkg, which would break the ABI */ if (!(options & PT_SILENT)) { (void) fprintf(stderr, pkg_gt(MSG_SIGNING), get_subject_display_name(pubcert)); } if (dump_hdr_and_pkgs(p7_bio, hdr, pkg) != 0) { progerr(gettext(ERR_NOGEN)); logerr(pkg_gt(MSG_GETVOL)); cleanup(); return (1); } BIO_flush(p7_bio); /* * now generate PKCS7 signature */ if (!PKCS7_dataFinal(sec_pkcs7, p7_bio)) { progerr(gettext(ERR_NOGEN)); logerr(pkg_gt(MSG_GETVOL)); cleanup(); return (1); } (void) BIO_free(p7_bio); } /* write out header to stream, which includes signature */ if (wdsheader(hdr, src, ods_name, pkg, sec_pkcs7)) { cleanup(); return (1); } if (sec_pkcs7 != NULL) { /* nuke in-memory signature for safety */ PKCS7_free(sec_pkcs7); sec_pkcs7 = NULL; } ds_volno = 1; /* number of volumes in datastream */ pinput = hdrbuf.text_buffer; /* skip past first line in header */ (void) mgets(line, 128); } if (signal_received > 0) { return (1); } errflg = 0; for (i = 0; pkg[i]; i++) { if (signal_received > 0) { return (1); } if (!(options & PT_ODTSTREAM) && dstdev.mount) { if (n = pkgmount(&dstdev, NULL, 0, 0, 1)) { cleanup(); return (n); } } if (errflg = pkgxfer(pkg[i], options)) { pkg[i] = NULL; if ((options & PT_ODTSTREAM) || (errflg != 2)) break; } else if (strcmp(dstinst, pkg[i])) pkg[i] = strdup(dstinst); } if (!(options & PT_ODTSTREAM) && dst) { pkgdir = strdup(dst); } /* * No cleanup of temporary directories created in this * function is done here. The calling function must do * the cleanup. */ return (signal_received > 0 ? 1 : errflg); }
// Write signed variable EFI_STATUS SetSignedVariable(IN CHAR16 *DatabaseName, IN EFI_GUID *DatabaseGuid, IN UINT32 Attributes, IN VOID *Database, IN UINTN DatabaseSize) { EFI_STATUS Status; EFI_VARIABLE_AUTHENTICATION_2 *Authentication; UINTN Size, NameLen; UINTN DataSize = 0; EFI_TIME Timestamp; VOID *Data = NULL; BIO *BioData = NULL; PKCS7 *p7; X509 *Certificate = NULL; EVP_PKEY *PrivateKey = NULL; const EVP_MD *md; // Check parameters if ((DatabaseName == NULL) || (DatabaseGuid == NULL)) { return EFI_INVALID_PARAMETER; } DBG("Setting secure variable: %g %s 0x%X (0x%X)\n", DatabaseGuid, DatabaseName, Database, DatabaseSize); NameLen = StrLen(DatabaseName); if (NameLen == 0) { return EFI_INVALID_PARAMETER; } // Get the current time DBG("Getting timestamp ...\n"); Status = GetUTCTime(&Timestamp); if (EFI_ERROR(Status)) { return Status; } DBG("Timestamp: %t\n", Timestamp); // In user mode we need to sign the database with exchange key if (!gSettings.SecureBootSetupMode) { // Initialize the cyphers and digests ERR_load_crypto_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); // Create signing certificate BioData = BIO_new_mem_buf((void *)gSecureBootExchangeKey, sizeof(gSecureBootExchangeKey)); if (BioData == NULL) { return EFI_OUT_OF_RESOURCES; } Certificate = PEM_read_bio_X509(BioData, NULL, NULL, NULL); BIO_free(BioData); if (Certificate == NULL) { return EFI_OUT_OF_RESOURCES; } // Create signing private key BioData = BIO_new_mem_buf((void *)gSecureBootExchangePrivateKey, sizeof(gSecureBootExchangePrivateKey)); if (BioData == NULL) { return EFI_OUT_OF_RESOURCES; } PrivateKey = PEM_read_bio_PrivateKey(BioData, NULL, NULL, NULL); BIO_free(BioData); if (PrivateKey == NULL) { X509_free(Certificate); return EFI_OUT_OF_RESOURCES; } // Do the actual signing process BioData = BIO_new(BIO_s_mem()); BIO_write(BioData, DatabaseName, (int)StrLen(DatabaseName)); BIO_write(BioData, DatabaseGuid, sizeof(EFI_GUID)); BIO_write(BioData, &Attributes, sizeof(UINT32)); BIO_write(BioData, &Timestamp, sizeof(EFI_TIME)); BIO_write(BioData, Database, (int)DatabaseSize); md = EVP_get_digestbyname("SHA256"); p7 = PKCS7_new(); PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_sign_add_signer(p7, Certificate, PrivateKey, md, PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOSMIMECAP); PKCS7_set_detached(p7, 1); PKCS7_final(p7, BioData, PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOSMIMECAP); X509_free(Certificate); EVP_PKEY_free(PrivateKey); DataSize = i2d_PKCS7(p7, NULL); Data = AllocateZeroPool(DataSize); i2d_PKCS7(p7, (unsigned char **)&Data); PKCS7_free(p7); // Set the authentication buffer size Size = sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16) + DataSize; } else { // In setup mode we don't need to sign, so just set the database DBG("In setup mode, not signing ...\n"); Size = sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16) + DatabaseSize; } // Create the authentication buffer DBG("Creating authentication ...\n"); Authentication = (EFI_VARIABLE_AUTHENTICATION_2 *)AllocateZeroPool(Size); if (Authentication == NULL) { if (Data != NULL) { FreePool(Data); } return EFI_OUT_OF_RESOURCES; } // Set the certificate elements CopyMem(&(Authentication->TimeStamp), &Timestamp, sizeof(EFI_TIME)); Authentication->AuthInfo.Hdr.dwLength = (UINT32)(sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16) + DataSize); Authentication->AuthInfo.Hdr.wRevision = 0x0200; Authentication->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; CopyMem(&(Authentication->AuthInfo.CertType), &gEfiCertPkcs7Guid, sizeof(EFI_GUID)); // Copy the data into the authentication if (Data != NULL) { CopyMem(((UINT8 *)Authentication) + sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16), Data, DataSize); FreePool(Data); } else { CopyMem(((UINT8 *)Authentication) + sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16), Database, DatabaseSize); //Payload, PayloadSize); } DBG("Writing secure variable 0x%X (0x%X) ...\n", Authentication, Size); // Write the database variable Status = gRT->SetVariable(DatabaseName, DatabaseGuid, SET_DATABASE_ATTRIBUTES, Size, Authentication); // Cleanup the authentication buffer FreePool(Authentication); return Status; }
static int add_auth_descriptor(varsign_context *ctx, unsigned char dont_sign) { EFI_VARIABLE_AUTHENTICATION_2 *auth; int rc=0, len=0, flags=0; EFI_TIME timestamp; const EVP_MD *md; BIO *data_bio = NULL; PKCS7 *p7; UINT8 *signpkg; if (set_timestamp(×tamp)) return -1; /* create a BIO for our variable data, containing: * * Variablename (not including trailing nul) * * VendorGUID * * Attributes * * TimeStamp * * Data */ if (dont_sign == 0) { data_bio = BIO_new(BIO_s_mem()); BIO_write(data_bio, ctx->var_name, ctx->var_name_bytes); BIO_write(data_bio, &ctx->var_guid, sizeof(ctx->var_guid)); BIO_write(data_bio, &ctx->var_attrs, sizeof(ctx->var_attrs)); BIO_write(data_bio, ×tamp, sizeof(timestamp)); BIO_write(data_bio, ctx->data, ctx->data_len); md = EVP_get_digestbyname("SHA256"); p7 = PKCS7_new(); flags = PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOSMIMECAP;; PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_sign_add_signer(p7, ctx->cert, ctx->key, md, flags); PKCS7_set_detached(p7, 1); rc = PKCS7_final(p7, data_bio, flags); if (!rc) { fprintf(stderr, "Error signing variable data\n"); ERR_print_errors_fp(stderr); BIO_free_all(data_bio); return -1; } len = i2d_PKCS7(p7, NULL); } else { len = 0; } /* set up our auth descriptor */ auth = talloc_size(ctx, len + offsetof (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData)); auth->TimeStamp = timestamp; auth->AuthInfo.Hdr.dwLength = len + offsetof (WIN_CERTIFICATE_UEFI_GUID, CertData); auth->AuthInfo.Hdr.wRevision = 0x0200; auth->AuthInfo.Hdr.wCertificateType = 0x0EF1; auth->AuthInfo.CertType = cert_pkcs7_guid; if (dont_sign == 0) { signpkg = auth->AuthInfo.CertData; i2d_PKCS7(p7, &signpkg); } ctx->auth_descriptor = auth; ctx->auth_descriptor_len = len + offsetof (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData); BIO_free_all(data_bio); return 0; }
static LUA_FUNCTION(openssl_pkcs7_sign_digest) { PKCS7 *p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7"); size_t l; const char* data = luaL_checklstring(L, 2, &l); long flags = luaL_optint(L, 3, 0); int hash = lua_isnoneornil(L, 4) ? 0 : lua_toboolean(L, 4); int ret = 0; int i, j; const EVP_MD* md; PKCS7_SIGNER_INFO *si; EVP_MD_CTX mdc; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; ASN1_OCTET_STRING *os = NULL; if (p7->d.ptr == NULL) { luaL_error(L, "pkcs7 without content"); return 0; } flags |= PKCS7_DETACHED; PKCS7_set_detached(p7, 1); EVP_MD_CTX_init(&mdc); i = OBJ_obj2nid(p7->type); p7->state = PKCS7_S_HEADER; switch (i) { case NID_pkcs7_data: os = p7->d.data; break; case NID_pkcs7_signedAndEnveloped: /* XXXXXXXXXXXXXXXX */ si_sk = p7->d.signed_and_enveloped->signer_info; os = p7->d.signed_and_enveloped->enc_data->enc_data; if (!os) { os = M_ASN1_OCTET_STRING_new(); if (!os) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); goto err; } p7->d.signed_and_enveloped->enc_data->enc_data = os; } break; case NID_pkcs7_enveloped: /* XXXXXXXXXXXXXXXX */ os = p7->d.enveloped->enc_data->enc_data; if (!os) { os = M_ASN1_OCTET_STRING_new(); if (!os) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); goto err; } p7->d.enveloped->enc_data->enc_data = os; } break; case NID_pkcs7_signed: si_sk = p7->d.sign->signer_info; os = PKCS7_get_octet_string(p7->d.sign->contents); /* If detached data then the content is excluded */ if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { M_ASN1_OCTET_STRING_free(os); os = NULL; p7->d.sign->contents->d.data = NULL; } break; case NID_pkcs7_digest: os = PKCS7_get_octet_string(p7->d.digest->contents); /* If detached data then the content is excluded */ if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { M_ASN1_OCTET_STRING_free(os); os = NULL; p7->d.digest->contents->d.data = NULL; } break; default: PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } if (si_sk != NULL) { for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); if (si->pkey == NULL) continue; j = OBJ_obj2nid(si->digest_alg->algorithm); md = EVP_get_digestbynid(j); EVP_DigestInit_ex(&mdc, md, NULL); if (hash) { if (l == (size_t) mdc.digest->ctx_size) { memcpy(mdc.md_data, data, l); } else { EVP_MD_CTX_cleanup(&mdc); luaL_argerror(L, 2, "data with wrong length"); } } else EVP_DigestUpdate(&mdc, data, l); sk = si->auth_attr; /* * If there are attributes, we add the digest attribute and only * sign the attributes */ if (sk_X509_ATTRIBUTE_num(sk) > 0) { if (!do_pkcs7_signed_attrib(si, &mdc)) goto err; } else { unsigned char *abuf = NULL; unsigned int abuflen; abuflen = EVP_PKEY_size(si->pkey); abuf = OPENSSL_malloc(abuflen); if (!abuf) goto err; if (!EVP_SignFinal(&mdc, abuf, &abuflen, si->pkey)) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); goto err; } ASN1_STRING_set0(si->enc_digest, abuf, abuflen); } } } else if (i == NID_pkcs7_digest) { unsigned char md_data[EVP_MAX_MD_SIZE]; unsigned int md_len; md = EVP_get_digestbynid(OBJ_obj2nid(p7->d.digest->md->algorithm)); EVP_DigestInit_ex(&mdc, md, NULL); if (l == (size_t) mdc.digest->ctx_size) { memcpy(mdc.md_data, data, l); } else { EVP_MD_CTX_cleanup(&mdc); luaL_error(L, "data with wrong data"); } if (!EVP_DigestFinal_ex(&mdc, md_data, &md_len)) goto err; M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); } if (!PKCS7_is_detached(p7)) { /* * NOTE(emilia): I think we only reach os == NULL here because detached * digested data support is broken. */ if (os == NULL) goto err; if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { char *cont = memdup(data, l); long contlen = l; ASN1_STRING_set0(os, (unsigned char *) cont, contlen); } } ret = 1; err: EVP_MD_CTX_cleanup(&mdc); return openssl_pushresult(L, ret); }