Test::Result PK_Signature_Verification_Test::run_one_test(const std::string&, const VarMap& vars) { const std::vector<uint8_t> message = get_req_bin(vars, "Msg"); const std::vector<uint8_t> signature = get_req_bin(vars, "Signature"); const std::string padding = get_opt_str(vars, "Padding", default_padding(vars)); std::unique_ptr<Botan::Public_Key> pubkey = load_public_key(vars); Test::Result result(algo_name() + "/" + padding + " signature verification"); for(auto&& verify_provider : possible_pk_providers()) { std::unique_ptr<Botan::PK_Verifier> verifier; try { verifier.reset(new Botan::PK_Verifier(*pubkey, padding, Botan::IEEE_1363, verify_provider)); result.test_eq("correct signature valid", verifier->verify_message(message, signature), true); check_invalid_signatures(result, *verifier, message, signature); } catch(Botan::Lookup_Error&) { result.test_note("Skipping verifying with " + verify_provider); } } return result; }
Test::Result PK_Signature_NonVerification_Test::run_one_test(const std::string& pad_hdr, const VarMap& vars) { const std::string padding = choose_padding(vars, pad_hdr); const std::vector<uint8_t> message = get_req_bin(vars, "Msg"); std::unique_ptr<Botan::Public_Key> pubkey = load_public_key(vars); const std::vector<uint8_t> invalid_signature = get_req_bin(vars, "InvalidSignature"); Test::Result result(algo_name() + "/" + padding + " verify invalid signature"); for(auto const& verify_provider : possible_providers(algo_name())) { std::unique_ptr<Botan::PK_Verifier> verifier; try { verifier.reset(new Botan::PK_Verifier(*pubkey, padding, Botan::IEEE_1363, verify_provider)); result.test_eq("incorrect signature rejected", verifier->verify_message(message, invalid_signature), false); } catch(Botan::Lookup_Error&) { result.test_note("Skipping verifying with " + verify_provider); } } return result; }
Test::Result PK_Signature_Verification_Test::run_one_test(const std::string&, const VarMap& vars) { const std::vector<uint8_t> message = get_req_bin(vars, "Msg"); const std::vector<uint8_t> signature = get_req_bin(vars, "Signature"); const std::string padding = get_opt_str(vars, "Padding", default_padding(vars)); std::unique_ptr<Botan::Public_Key> pubkey = load_public_key(vars); Test::Result result(algo_name() + "/" + padding + " signature verification"); Botan::PK_Verifier verifier(*pubkey, padding); result.test_eq("correct signature valid", verifier.verify_message(message, signature), true); check_invalid_signatures(result, verifier, message, signature); return result; }
/* * Check the crypto signature on the image... * This always includes a public key encrypted header and an MD5 * (or SHA256) checksum. It optionally includes AES encryption of * the image. */ static int check_crypto_signature(void) { struct header hdr; int hash_length; unsigned long fblength, length; unsigned char *data; RSA *pkey; #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 unsigned char hash[SHA256_DIGEST_LENGTH]; #else unsigned char hash[MD5_DIGEST_LENGTH]; #endif if (!load_public_key(&pkey)) return CRYPTO_CHECK_NO_PUBLICKEY; if (!decode_header_info(&hdr, pkey, &hash_length)) return CRYPTO_CHECK_NO_HEADER; RSA_free(pkey); /* Decrypt image if needed */ if (hdr.flags & FLAG_ENCRYPTED) { unsigned char cin[AES_BLOCK_SIZE]; unsigned char cout[AES_BLOCK_SIZE]; unsigned long s; AES_KEY key; if (fb_seek_set(0) < 0) { error("Can not decrypt encrypted image when -t option is used."); exit(BAD_CRYPT); } if ((hash_length % AES_BLOCK_SIZE) != 0) { error("image size not miscable with cryptography"); exit(BAD_CRYPT); } AES_set_decrypt_key(hdr.aeskey, AESKEYSIZE * 8, &key); /* Convert the body of the file */ for (s = 0; s < hash_length; s += AES_BLOCK_SIZE) { fb_peek(cin, AES_BLOCK_SIZE); AES_decrypt(cin, cout, &key); fb_write(cout, AES_BLOCK_SIZE); } } /* Remove padding */ if (hdr.padsize) { hash_length -= hdr.padsize; #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 fb_meta_add(hdr.padsize); #else fb_trim(hdr.padsize); #endif } if (crypto_hash_init) { if (crypto_hash_total > hash_length) { error("hashed too much, try without -t"); exit(BAD_MD5_SIG); } fb_seek_set(crypto_hash_total); } else { #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 SHA256_Init(&sha_ctx); #else MD5_Init(&md5_ctx); #endif fb_seek_set(0); } while ((data = fb_read_block(&fblength)) != NULL) { length = fblength; if (length > (hash_length - crypto_hash_total)) { length = hash_length - crypto_hash_total; } #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 SHA256_Update(&sha_ctx, data, length); #else MD5_Update(&md5_ctx, data, length); #endif if (length != fblength) break; crypto_hash_total += length; } #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 SHA256_Final(hash, &sha_ctx); if (memcmp(hdr.hash, hash, SHA256_DIGEST_LENGTH) != 0) { error("bad SHA256 signature"); exit(BAD_MD5_SIG); } #else MD5_Final(hash, &md5_ctx); if (memcmp(hdr.md5, hash, MD5_DIGEST_LENGTH) != 0) { error("bad MD5 signature"); exit(BAD_MD5_SIG); } #endif notice("signed image approved"); return CRYPTO_CHECK_OK; }