size_t test_x509() { auto& rng = test_rng(); const std::string hash_fn = "SHA-256"; size_t fails = 0; /* Create the CA's key and self-signed cert */ RSA_PrivateKey ca_key(rng, 2048); X509_Certificate ca_cert = X509::create_self_signed_cert(ca_opts(), ca_key, hash_fn, rng); /* Create user #1's key and cert request */ DSA_PrivateKey user1_key(rng, DL_Group("dsa/botan/2048")); PKCS10_Request user1_req = X509::create_cert_req(req_opts1(), user1_key, "SHA-1", rng); /* Create user #2's key and cert request */ #if defined(BOTAN_HAS_ECDSA) EC_Group ecc_domain(OID("1.2.840.10045.3.1.7")); ECDSA_PrivateKey user2_key(rng, ecc_domain); #else RSA_PrivateKey user2_key(rng, 1536); #endif PKCS10_Request user2_req = X509::create_cert_req(req_opts2(), user2_key, hash_fn, rng); /* Create the CA object */ X509_CA ca(ca_cert, ca_key, hash_fn); /* Sign the requests to create the certs */ X509_Certificate user1_cert = ca.sign_request(user1_req, rng, X509_Time("2008-01-01"), X509_Time("2100-01-01")); X509_Certificate user2_cert = ca.sign_request(user2_req, rng, X509_Time("2008-01-01"), X509_Time("2100-01-01")); X509_CRL crl1 = ca.new_crl(rng); /* Verify the certs */ Certificate_Store_In_Memory store; store.add_certificate(ca_cert); Path_Validation_Restrictions restrictions(false); Path_Validation_Result result_u1 = x509_path_validate(user1_cert, restrictions, store); if(!result_u1.successful_validation()) { std::cout << "FAILED: User cert #1 did not validate - " << result_u1.result_string() << std::endl; ++fails; } Path_Validation_Result result_u2 = x509_path_validate(user2_cert, restrictions, store); if(!result_u2.successful_validation()) { std::cout << "FAILED: User cert #2 did not validate - " << result_u2.result_string() << std::endl; ++fails; } store.add_crl(crl1); std::vector<CRL_Entry> revoked; revoked.push_back(CRL_Entry(user1_cert, CESSATION_OF_OPERATION)); revoked.push_back(user2_cert); X509_CRL crl2 = ca.update_crl(crl1, revoked, rng); store.add_crl(crl2); result_u1 = x509_path_validate(user1_cert, restrictions, store); if(result_u1.result() != Certificate_Status_Code::CERT_IS_REVOKED) { std::cout << "FAILED: User cert #1 was not revoked - " << result_u1.result_string() << std::endl; ++fails; } result_u2 = x509_path_validate(user2_cert, restrictions, store); if(result_u2.result() != Certificate_Status_Code::CERT_IS_REVOKED) { std::cout << "FAILED: User cert #2 was not revoked - " << result_u2.result_string() << std::endl; ++fails; } revoked.clear(); revoked.push_back(CRL_Entry(user1_cert, REMOVE_FROM_CRL)); X509_CRL crl3 = ca.update_crl(crl2, revoked, rng); store.add_crl(crl3); result_u1 = x509_path_validate(user1_cert, restrictions, store); if(!result_u1.successful_validation()) { std::cout << "FAILED: User cert #1 was not un-revoked - " << result_u1.result_string() << std::endl; ++fails; } check_against_copy(ca_key, rng); check_against_copy(user1_key, rng); check_against_copy(user2_key, rng); test_report("X509", 0, fails); return fails; }
size_t test_nist_x509() { const std::string root_test_dir = "src/tests/data/nist_x509/"; const size_t total_tests = 76; try { // Do nothing, just test filesystem access get_files_recursive(root_test_dir); } catch(No_Filesystem_Access) { std::cout << "Warning: No filesystem access, skipping NIST X.509 validation tests" << std::endl; return 0; } size_t unexp_failure = 0; size_t unexp_success = 0; size_t wrong_error = 0; size_t skipped = 0; size_t ran = 0; auto expected_results = get_expected(); try { for(size_t test_no = 1; test_no <= total_tests; ++test_no) { const std::string test_dir = root_test_dir + "/test" + (test_no <= 9 ? "0" : "") + std::to_string(test_no); const std::vector<std::string> all_files = get_files_recursive(test_dir); if (all_files.empty()) std::cout << "Warning: No test files found in '" << test_dir << "'" << std::endl; std::vector<std::string> certs, crls; std::string root_cert, to_verify; for(const auto ¤t : all_files) { if(current.find("int") != std::string::npos && current.find(".crt") != std::string::npos) certs.push_back(current); else if(current.find("root.crt") != std::string::npos) root_cert = current; else if(current.find("end.crt") != std::string::npos) to_verify = current; else if(current.find(".crl") != std::string::npos) crls.push_back(current); } if(expected_results.find(test_no) == expected_results.end()) { skipped++; continue; } ++ran; Certificate_Store_In_Memory store; store.add_certificate(X509_Certificate(root_cert)); X509_Certificate end_user(to_verify); for(size_t i = 0; i != certs.size(); i++) store.add_certificate(X509_Certificate(certs[i])); for(size_t i = 0; i != crls.size(); i++) { DataSource_Stream in(crls[i], true); X509_CRL crl(in); store.add_crl(crl); } Path_Validation_Restrictions restrictions(true); Path_Validation_Result validation_result = x509_path_validate(end_user, restrictions, store); auto expected = expected_results[test_no]; Path_Validation_Result::Code result = validation_result.result(); if(result != expected) { std::cout << "NIST X.509 test #" << test_no << ": "; const std::string result_str = Path_Validation_Result::status_string(result); const std::string exp_str = Path_Validation_Result::status_string(expected); if(expected == Certificate_Status_Code::VERIFIED) { std::cout << "unexpected failure: " << result_str << std::endl; unexp_failure++; } else if(result == Certificate_Status_Code::VERIFIED) { std::cout << "unexpected success, expected " << exp_str << std::endl; unexp_success++; } else { std::cout << "wrong error, got '" << result_str << "' expected '" << exp_str << "'" << std::endl; wrong_error++; } } } } catch(std::exception& e) { std::cout << e.what() << std::endl; ++unexp_failure; } const size_t all_failures = unexp_failure + unexp_success + wrong_error; test_report("NIST X.509 path validation", ran, all_failures); return all_failures; }