int main( int argc, char **argv) { OPEN_LOG("check_signature", LOG_USER); if (argc != 3) FATAL(MSG_USAGE); struct Certificate locert, hicert; struct CertificateRevocationList crl; Certificate(&locert, (ushort) 0); Certificate(&hicert, (ushort) 0); CertificateRevocationList(&crl, (ushort) 0); struct Blob blob; Blob(&blob, (ushort) 0); struct casn *tbsp, *sigp; struct AlgorithmIdentifier *algp; char *sfx = strchr(argv[1], (int)'.'); int ansr; if (!strcmp(sfx, ".cer")) { tbsp = &locert.toBeSigned.self; algp = &locert.algorithm; sigp = &locert.signature; ansr = get_casn_file(&locert.self, argv[1], 0); } else if (!strcmp(sfx, ".crl")) { tbsp = &crl.toBeSigned.self; algp = &crl.algorithm; sigp = &crl.signature; ansr = get_casn_file(&crl.self, argv[1], 0); } else if (!strcmp(sfx, ".blb")) { tbsp = &blob.toBeSigned; algp = &blob.algorithm; sigp = &blob.signature; ansr = get_casn_file(&blob.self, argv[1], 0); } else FATAL(MSG_TYPE, argv[1]); if (ansr < 0) FATAL(MSG_GET, argv[1]); if (get_casn_file(&hicert.self, argv[2], 0) < 0) FATAL(MSG_GET, argv[2]); if (diff_objid(&algp->algorithm, id_sha_256WithRSAEncryption)) { char oidbuf[80]; read_objid(&algp->algorithm, oidbuf); FATAL(MSG_ALG, oidbuf); } if (!check_signature(tbsp, &hicert, sigp)) fprintf(stderr, "Signature failed\n"); fprintf(stderr, "Signature succeeded\n"); return 0; }
int main( int argc, char **argv) { struct Certificate cert; Certificate(&cert, (ushort) 0); if (argc < 3) FATAL(MSG_USAGE); if (get_casn_file(&cert.self, argv[1], 0) <= 0) FATAL(MSG_OPEN, argv[1]); struct RelativeDistinguishedName *rdnp = (struct RelativeDistinguishedName *)member_casn(&cert.toBeSigned. subject.rDNSequence. self, 0); struct AttributeValueAssertion *avap = (struct AttributeValueAssertion *)member_casn(&rdnp->self, 0); if (write_casn (&avap->value.commonName.printableString, (uchar *) argv[2], strlen(argv[2])) < 0) FATAL(MSG_WRITING, "name"); if (put_casn_file(&cert.self, argv[1], 0) < 0) FATAL(MSG_WRITING, argv[1]); DONE(MSG_OK, argv[1]); return 0; }
/* * Take values from the parents certificateand write them to the * current certificate. * val is filename of the parent certificate * fields of interest: * signature algorithm ID - overwrite (from template) * issuer - if filled in then don't overwrite * aki - use ski from issuer's cert * algorithm ID overwrite (from template) */ int use_parent_cert( void *cert, void *val) { struct Certificate issuer; struct Certificate *certp = (struct Certificate *)cert; struct CertificateToBeSigned *ctftbsp = &certp->toBeSigned; Certificate(&issuer, (ushort) 0); struct Extension *iextp, *cextp; // if not parent cert or we are self signed (and shouldn't have a parent // cert) if ((val == NULL) || (selfSigned)) return SUCCESS; // fprintf(stdout,"getting issuers cert %s\n", (char *)val); if (get_casn_file(&issuer.self, val, 0) < 0) { fprintf(stdout, "can't use issuers cert %s", (char *)val); return -1; } // copy algorithm identifiers (overwrite template value) // fprintf(stdout,"trying to copy algorithm identifiers\n"); copy_casn(&certp->algorithm.self, &issuer.toBeSigned.signature.self); copy_casn(&ctftbsp->signature.self, &issuer.toBeSigned.signature.self); // fprintf(stdout,"copied algorithm identifiers\n"); // copy subject name from issuer cert into issuer name in cert if issuer // name // not filled in. copy_casn(&ctftbsp->issuer.self, &issuer.toBeSigned.subject.self); // fprintf(stdout,"copied issuer name\n"); // replace aki extension of certificate with ski from issuer's cert cextp = find_extension(&ctftbsp->extensions, id_authKeyId, false); if (!cextp) cextp = make_extension(&ctftbsp->extensions, id_authKeyId); // fprintf(stdout,"copying ski as aki\n"); if ((iextp = find_extension(&issuer.toBeSigned.extensions, id_subjectKeyIdentifier, false))) { copy_casn(&cextp->extnValue.authKeyId.keyIdentifier, &iextp->extnValue.subjectKeyIdentifier); } else { fprintf(stdout, "Error: issuer cert has no SKI. AKI not set."); delete_casn(&issuer.self); return -1; } delete_casn(&issuer.self); return (SUCCESS); }
int main( int argc, char **argv) { OPEN_LOG("cert_validate", LOG_USER); if (argc != 3) FATAL(MSG_USAGE); struct Certificate locert, hicert; Certificate(&locert, (ushort) 0); Certificate(&hicert, (ushort) 0); if (get_casn_file(&locert.self, argv[1], 0) < 0) FATAL(MSG_GET, argv[1]); if (get_casn_file(&hicert.self, argv[2], 0) < 0) FATAL(MSG_GET, argv[2]); if (!check_cert_signature(&locert, &hicert)) FATAL(MSG_SIG, "Failed"); DONE(MSG_SIG, "succeeded"); return 0; }
void CertificatesScreen::addCertificate(std::string name, std::string id) { certificate_list.push_back(Certificate(this, name, id)); std::list<Certificate>::iterator new_cert= --certificate_list.end(); new_cert->myIter=new_cert; menu.addPrompt(NULL, &*new_cert); if (jumpto == id) { foundfocus=true; focusTo=new_cert; } }
void CertificateFetcher::fetch(const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state, const ValidationContinuation& continueValidation) { BOOST_ASSERT(m_certStorage != nullptr); auto cert = m_certStorage->getUnverifiedCertCache().find(certRequest->interest); if (cert != nullptr) { NDN_LOG_DEBUG_DEPTH("Found certificate in **un**verified key cache " << cert->getName()); continueValidation(*cert, state); return; } doFetch(certRequest, state, [continueValidation, this] (const Certificate& cert, const shared_ptr<ValidationState>& state) { m_certStorage->cacheUnverifiedCert(Certificate(cert)); continueValidation(cert, state); }); }
void CertificateFetcherFromNetwork::dataCallback(const Data& data, const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state, const ValidationContinuation& continueValidation) { NDN_LOG_DEBUG_DEPTH("Fetched certificate from network " << data.getName()); Certificate cert; try { cert = Certificate(data); } catch (const tlv::Error& e) { return state->fail({ValidationError::Code::MALFORMED_CERT, "Fetched a malformed certificate " "`" + data.getName().toUri() + "` (" + e.what() + ")"}); } continueValidation(cert, state); }
int main( int argc, char **argv) { struct Certificate cert; int certnum; Certificate(&cert, (ushort) 0); if (argc < 3) FATAL(MSG_USAGE); if (get_casn_file(&cert.self, argv[1], 0) <= 0) FATAL(MSG_OPEN, argv[1]); if (sscanf(argv[2], "%d", &certnum) != 1) FATAL(MSG_READING, "serial number"); if (write_casn_num(&cert.toBeSigned.serialNumber, certnum) < 0) FATAL(MSG_WRITING, "serial number"); if (put_casn_file(&cert.self, argv[1], 0) < 0) FATAL(MSG_WRITING, argv[1]); DONE(MSG_OK, argv[1]); return 0; }
int main( int argc, char **argv) { struct Certificate cert; int lth; Certificate(&cert, (ushort) 0); if (argc == 0 || argc < 3) FATAL(MSG_USAGE); lth = get_casn_file(&cert.self, argv[1], 0); struct casn *casnp = &cert.toBeSigned.serialNumber; if ((lth = vsize_casn(casnp)) < 6) FATAL(MSG_SN); struct Extension *extp; if (!(extp = find_extension(&cert.toBeSigned.extensions, id_pe_ipAddrBlock, 0))) FATAL(MSG_EXT, "IPAddress"); struct Extensions extensions; Extensions(&extensions, (ushort) 0); if ((lth = get_casn_file(&extensions.self, argv[2], 0)) < 0) FATAL(MSG_OPEN, argv[2]); struct Extension *sbextp = (struct Extension *)member_casn(&extensions.self, 0); // ip // Addresses uchar *sb = (uchar *) calloc(1, size_casn(&sbextp->self)); read_casn(&sbextp->self, sb); uchar *b = (uchar *) calloc(1, size_casn(&extp->self)); read_casn(&extp->self, b); if (diff_casn(&sbextp->self, &extp->self)) FATAL(MSG_IN, "IP Addresses"); sbextp = (struct Extension *)next_of(&sbextp->self); if (!(extp = find_extension(&cert.toBeSigned.extensions, id_pe_autonomousSysNum, 0))) FATAL(MSG_EXT, "AS number"); if (diff_casn(&sbextp->self, &extp->self)) FATAL(MSG_IN, "AS numbers"); DONE(MSG_OK, argv[1]); return 0; }
int main( int argc, char *argv[]) { int delete_existing = 0; /* delete existing SIA access descriptions */ const char *file = NULL; /* certificate file */ struct Certificate cert; /* ASN.1 certificate object */ struct Extension *extp; /* ASN.1 X.509 extension pointer */ struct SubjectInfoAccess *siap; /* ASN.1 SIA pointer */ int c = 0; /* getopt option character */ int i; /* loop counter */ int ret; /* return value */ /* * Parse command line arguments. */ opterr = 0; while ((c = getopt(argc, argv, "dr:m:s:h")) != -1) { switch (c) { case 'd': delete_existing = 1; break; case 'r': /* id-ad-caRepository */ if (add_sia_request('r', optarg) != 0) { fprintf(stderr, "Error: failed to add URI request -r %s\n", optarg); return -1; } break; case 'm': /* id-ad-rpkiManifest */ if (add_sia_request('m', optarg) != 0) { fprintf(stderr, "Error: failed to add URI request -m %s\n", optarg); return -1; } break; case 's': /* id-ad-signedObject */ if (add_sia_request('s', optarg) != 0) { fprintf(stderr, "Error: failed to add URI request -s %s\n", optarg); return -1; } break; case 'h': usage(argc, argv); return -1; case '?': if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c'.\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); usage(argc, argv); return -1; default: usage(argc, argv); return -1; } } if (optind >= argc) { /* no arguments remain? */ usage(argc, argv); return -1; } file = argv[optind]; /* * Parse certificate. */ Certificate(&cert, (unsigned short)0); /* constructor */ ret = get_casn_file(&cert.self, (char *)file, 0); if (ret < 0) { fprintf(stderr, "Could not open file: %s\n", file); return -2; } /* * Find or create SIA extension. */ extp = find_extension(&cert.toBeSigned.extensions, id_pe_subjectInfoAccess, false); if (!extp) { extp = make_extension(&cert.toBeSigned.extensions, id_pe_subjectInfoAccess); if (!extp) { fprintf(stderr, "Could not create SIA extension.\n"); return -3; } } siap = &extp->extnValue.subjectInfoAccess; /* * Optionally delete existing AccessDescriptions. */ if (delete_existing) { clear_casn(&siap->self); /* This messes up the "DEFINED BY" * flag, so we need to set it again in * the next line. */ if (write_objid(&extp->extnID, id_pe_subjectInfoAccess) < 0) { fprintf(stderr, "Error clearing existing URIs.\n"); return -1; } } /* * For each AccessDescription request, insert it. */ for (i = 0; i < num_sia_requests; i++) { int current_size; struct AccessDescription *adp; /* ASN.1 AccessDescription pointer */ /* * Append new entry. */ current_size = num_items(&siap->self); adp = (struct AccessDescription *)inject_casn(&siap->self, current_size); if (!adp) { fprintf(stderr, "Error: failed to append access description.\n"); return -1; } if (write_objid(&adp->accessMethod, (char *)sia_requests[i].accessMethod) < 0) { fprintf(stderr, "Error: failed to set access method.\n"); return -1; } if (write_casn(&adp->accessLocation.url, (unsigned char *)sia_requests[i].accessLocation, strlen(sia_requests[i].accessLocation)) < 0) { fprintf(stderr, "Error: failed to set access location.\n"); return -1; } } /* * Check for non-empty SIA (RFC 5280) */ if (num_items(&siap->self) == 0) { fprintf(stderr, "SIA must have at least one AccessDescription, per RFC5280.\n"); return -1; } /* * Write to file. */ if (put_casn_file(&cert.self, (char *)file, 0) < 0) { fprintf(stderr, "Error: failed to write %s\n", file); return -4; } /* * Clean up. */ delete_casn(&cert.self); return 0; }
int main( int argc, char *argv[]) { int c = 0; /* command line option character */ int option_dir = 0; /* retrieve SIA directory URL */ int option_mft = 0; /* retrieve SIA manifest URL */ const char *file = NULL; /* certificate file */ struct Certificate cert; /* ASN.1 certificate object */ struct Extension *extp; /* ASN.1 X.509 extension pointer */ struct SubjectInfoAccess *siap; /* ASN.1 SIA pointer */ struct AccessDescription *adp; /* ASN.1 AccessDescription pointer */ int ret; /* return value */ /* * Parse command line arguments. */ opterr = 0; while ((c = getopt(argc, argv, "dm")) != -1) { switch (c) { case 'd': option_dir = 1; break; case 'm': option_mft = 1; break; case '?': if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c'.\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); usage(argc, argv); return -1; default: usage(argc, argv); return -1; } } /* * If no selection, default to directory. */ if (option_dir == 0 && option_mft == 0) option_dir = 1; if (optind >= argc) { usage(argc, argv); return -1; } file = argv[optind]; /* * Parse certificate. */ Certificate(&cert, (unsigned short)0); /* constructor */ ret = get_casn_file(&cert.self, (char *)file, 0); if (ret < 0) { fprintf(stderr, "Could not open file: %s\n", file); return -2; } /* * Find SIA extension. */ extp = find_extension(&cert.toBeSigned.extensions, id_pe_subjectInfoAccess, false); if (!extp) { fprintf(stderr, "Error: could not locate SIA extension.\n"); return -3; } siap = &extp->extnValue.subjectInfoAccess; /* * For each AccessDescription, print the accessLocation URI if the * accessMethod matches the user requested SIA type: directory or * manifest. */ for (adp = (struct AccessDescription *)member_casn(&siap->self, 0); adp != NULL; adp = (struct AccessDescription *)next_of(&adp->self)) { char *rsync_uri = NULL; int len = 0; int print_this_one = 0; if (diff_objid(&adp->accessMethod, id_ad_rpkiManifest) == 0 && option_mft) { /* * Manifest */ print_this_one = 1; } else if (diff_objid(&adp->accessMethod, id_ad_caRepository) == 0 && option_dir) { /* * Directory */ print_this_one = 1; } else if (diff_objid(&adp->accessMethod, id_ad_signedObject) == 0) { /* * Signed Object */ print_this_one = 1; } if (!print_this_one) continue; /* * print manifest URI */ len = vsize_casn(&adp->accessLocation.self); rsync_uri = (char *)calloc(len + 2, 1); if (!rsync_uri) { fprintf(stderr, "Memory allocation failure on %d bytes!\n", len + 2); continue; } ret = read_casn(&adp->accessLocation.self, (unsigned char *)rsync_uri); if (ret < len) { fprintf(stderr, "Read failure: got %d, expected %d bytes\n", ret, len); } else { printf("%s\n", rsync_uri); } free(rsync_uri); } /* * Clean up. */ delete_casn(&cert.self); return 0; }
/* * Create an EE or CA certificate using the * table to set the fields. The table is build * using command line arguments */ int create_cert( struct object_field *table) { int ret = 0; int i; struct Certificate cert; Certificate(&cert, (ushort) 0); // constructor for the cert struct char *keyfile = NULL, *val; int val_type; eecert = 0; // is it a ca or ee cert if ((ret = setEEorCA(table)) != SUCCESS) return ret; setSelfSigned(table); // Read the certificate template into the certificate if (!templateFile) { if (eecert) templateFile = CONFIG_TEMPLATE_EE_CERT_get(); else templateFile = CONFIG_TEMPLATE_CA_CERT_get(); } ret = get_casn_file(&cert.self, (char *)templateFile, 0); if (ret < 0) { warn(FILE_OPEN_ERR, (char *)templateFile); return (FILE_OPEN_ERR); } // clear out fields in the template (only keeping a few); clear_cert(&cert); // fill in the default fields write_default_fields(&cert); // Populate the certificate fields with data from the // table. Note the table is populated from input arguments // If there is no function to call and the argument is optional then // it is ok otherwise it is an error. for (i = 0; table[i].name != NULL; i++) { if (table[i].func != NULL) { if (table[i].value != NULL) { if (table[i].func(&cert.self, table[i].value) < 0) { fprintf(stderr, "Error writing %s into field %s\n", table[i].value, table[i].name); } } else { if (table[i].required) fprintf(stderr, "Missing value for %s\n", table[i].name); } } } // if signature value is set in the table, write that value as the // signature, // otherwise sign it if (get_table_value("signatureValue", table, &val, &val_type) != 0) { fprintf(stdout, "Error writing signature"); return (-1); } if (val != NULL) // input signature { if (write_sig(&cert, val) != SUCCESS) { fprintf(stdout, "Error writing signature"); return (-1); } } else { // have to sign it, get key from subject // keyfile if selfsigned else parents if (selfSigned) get_table_value("subjkeyfile", table, &keyfile, &val_type); else get_table_value("parentkeyfile", table, &keyfile, &val_type); if (keyfile == NULL || (sign_cert(&cert, keyfile) != SUCCESS)) return -1; } // write out the certificate using the ouput filename if (get_table_value("outputfilename", table, &val, &val_type) < 0) { warn(FILE_WRITE_ERR, "outputfilename missing"); return (FILE_WRITE_ERR); } if (put_casn_file(&cert.self, val, 0) < 0) { warn(FILE_WRITE_ERR, val); return (FILE_WRITE_ERR); } else warn(SUCCESS, val); return (SUCCESS); }
int main( int argc, char **argv) { /* * Args are: file TBS, keyfile, [update] */ struct Certificate cert; Certificate(&cert, (ushort) 0); struct CertificateRevocationList crl; CertificateRevocationList(&crl, (ushort) 0); struct Blob blob; Blob(&blob, (ushort) 0); struct AlgorithmIdentifier *algp, *tbsalgp; struct casn *casnp, *sigp, *selfp; const char *keyfile = NULL; OPEN_LOG("sign_cert", LOG_USER); if (argc < 3) FATAL(MSG_USAGE); char *sfx = strrchr(argv[1], (int)'.'); keyfile = argv[2]; if (!strcmp(sfx, ".cer")) { selfp = &cert.self; casnp = &cert.toBeSigned.self; tbsalgp = &cert.toBeSigned.signature; sigp = &cert.signature; algp = &cert.algorithm; } else if (!strcmp(sfx, ".crl")) { selfp = &crl.self; casnp = &crl.toBeSigned.self; tbsalgp = &crl.toBeSigned.signature; sigp = &crl.signature; algp = &crl.algorithm; } else if (!strcmp(sfx, ".blb")) { selfp = &blob.self; casnp = &blob.toBeSigned; tbsalgp = NULL; sigp = &blob.signature; algp = &blob.algorithm; } else { FATAL(MSG_UNK_EXT, argv[1]); } if (get_casn_file(selfp, argv[1], 0) < 0) FATAL(MSG_OPEN, argv[1]); if (argv[3] && (*argv[3] & 1)) { if (!strcmp(sfx, ".cer")) adjust_time(&cert.toBeSigned.validity.notBefore.utcTime, &cert.toBeSigned.validity.notAfter.utcTime); else if (!strcmp(sfx, ".crl")) adjust_time((struct casn *)&crl.toBeSigned.lastUpdate, (struct casn *)&crl.toBeSigned.nextUpdate); } if (tbsalgp && (!argv[3] || !(*argv[3] & 2))) { write_objid(&tbsalgp->algorithm, id_sha_256WithRSAEncryption); write_casn(&tbsalgp->parameters.rsadsi_SHA256_WithRSAEncryption, (uchar *) "", 0); } if (!set_signature(casnp, sigp, keyfile, "label", "password", false)) { FATAL(MSG_IN, "set_signature()"); } if (!argv[3] || !(*argv[3] & 4)) { write_objid(&algp->algorithm, id_sha_256WithRSAEncryption); write_casn(&algp->parameters.rsadsi_SHA256_WithRSAEncryption, (uchar *) "", 0); } put_casn_file(selfp, argv[1], 0); DONE(MSG_OK, argv[1]); return 0; }
RouterContext::RouterContext(std::shared_ptr<Database> const &db, boost::asio::io_service &ios) : m_db(db), m_ios(ios), m_inMsgDispatcher(ios, *this), m_outMsgDispatcher(*this), m_signals(ios), m_tunnelManager(ios, *this), m_profileManager(*this), m_peerManager(ios, *this) { // Load the private keys from the database Botan::AutoSeeded_RNG rng; std::string encryptingKeyPEM = m_db->getConfigValue("private_encryption_key"); Botan::DataSource_Memory dsm((unsigned char *)encryptingKeyPEM.data(), encryptingKeyPEM.size()); m_encryptionKey = std::shared_ptr<Botan::ElGamal_PrivateKey>(dynamic_cast<Botan::ElGamal_PrivateKey *>(Botan::PKCS8::load_key(dsm, rng, (std::string)""))); std::string signingKeyPEM = m_db->getConfigValue("private_signing_key"); Botan::DataSource_Memory dsm2((unsigned char *)signingKeyPEM.data(), signingKeyPEM.size()); m_signingKey = std::shared_ptr<Botan::DSA_PrivateKey>(dynamic_cast<Botan::DSA_PrivateKey *>(Botan::PKCS8::load_key(dsm2, rng, (std::string)""))); Botan::BigInt encryptionKeyPublic, signingKeyPublic; encryptionKeyPublic = m_encryptionKey->get_y(); signingKeyPublic = m_signingKey->get_y(); ByteArray encryptionKeyBytes = Botan::BigInt::encode(encryptionKeyPublic), signingKeyBytes = Botan::BigInt::encode(signingKeyPublic); m_identity = std::make_shared<RouterIdentity>(encryptionKeyBytes, signingKeyBytes, Certificate()); m_dht = std::make_shared<DHT::DHTFacade>(ios, m_identity->getHash(), db->getAllHashes(), *this); }
Certificate Certificate::self_signed ( Provider& provider, string subject ) { // Generate a new exportable exchange key. const Key::Type key_type = Key::Type::exchange(); Key key = Key::generate (provider, key_type, Key::Hints().exportable()); ::PCCERT_CONTEXT certificate = 0; // Create a certificate name blob. ::CERT_NAME_BLOB name = { 0 }; char cb[1000] = {0}; name.pbData = (BYTE*)cb; name.cbData = 1000; const ::DWORD encoding = CRYPT_ASN_ENCODING; if (!::CertStrToNameW(encoding, subject.data(), 0, 0, name.pbData, &name.cbData, 0)) { const ::DWORD error = ::GetLastError(); UNCHECKED_WIN32C_ERROR(CertStrToName, error); } // Describe the key provider. string provider_name = provider.name(); string container = provider.container(); ::CRYPT_KEY_PROV_INFO info = {0}; info.pwszContainerName = container.data(); info.pwszProvName = provider_name.data(); info.dwProvType = provider.type(); info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID; info.dwKeySpec = key_type; // Expire certificate 1 year from now. w32::Time expiry = w32::Time::now() + 1*w32::Delta::year(); // Create the self-signed certificate. ::CERT_EXTENSIONS extensions; ::ZeroMemory(&extensions, sizeof(extensions)); certificate = ::CertCreateSelfSignCertificate (provider.handle(), &name, 0, &info, 0, 0, &expiry.data(), &extensions); if (certificate == 0) { const ::DWORD error = ::GetLastError(); UNCHECKED_WIN32C_ERROR(CertCreateSelfSignCertificate, error); } const Handle handle = claim(certificate); // Verify that the certificate was store on the local machine. const ::BOOL found = ::CryptFindCertificateKeyProvInfo (certificate, CRYPT_FIND_MACHINE_KEYSET_FLAG, 0); if (found == FALSE) { const ::DWORD error = ::GetLastError(); if (error == NTE_NO_KEY) { // ..? } UNCHECKED_WIN32C_ERROR(CryptFindCertificateKeyProvInfo, error); } return (Certificate(handle)); }