15acaca2fSWilliam A. Kennington III /* 25acaca2fSWilliam A. Kennington III * Copyright 2021 Google LLC 35acaca2fSWilliam A. Kennington III * 45acaca2fSWilliam A. Kennington III * Licensed under the Apache License, Version 2.0 (the "License"); 55acaca2fSWilliam A. Kennington III * you may not use this file except in compliance with the License. 65acaca2fSWilliam A. Kennington III * You may obtain a copy of the License at 75acaca2fSWilliam A. Kennington III * 85acaca2fSWilliam A. Kennington III * http://www.apache.org/licenses/LICENSE-2.0 95acaca2fSWilliam A. Kennington III * 105acaca2fSWilliam A. Kennington III * Unless required by applicable law or agreed to in writing, software 115acaca2fSWilliam A. Kennington III * distributed under the License is distributed on an "AS IS" BASIS, 125acaca2fSWilliam A. Kennington III * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135acaca2fSWilliam A. Kennington III * See the License for the specific language governing permissions and 145acaca2fSWilliam A. Kennington III * limitations under the License. 155acaca2fSWilliam A. Kennington III */ 16*adb8ffe4SWilly Tu 17*adb8ffe4SWilly Tu #include <libcr51sign/libcr51sign.h> 185acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign_support.h> 19deb5501aSWilliam A. Kennington III #include <openssl/err.h> 205acaca2fSWilliam A. Kennington III #include <openssl/evp.h> 215acaca2fSWilliam A. Kennington III #include <openssl/pem.h> 225acaca2fSWilliam A. Kennington III #include <openssl/rsa.h> 235acaca2fSWilliam A. Kennington III #include <stdio.h> 245acaca2fSWilliam A. Kennington III 255acaca2fSWilliam A. Kennington III #ifdef __cplusplus 265acaca2fSWilliam A. Kennington III extern "C" 275acaca2fSWilliam A. Kennington III { 285acaca2fSWilliam A. Kennington III #endif 295acaca2fSWilliam A. Kennington III 30deb5501aSWilliam A. Kennington III #ifndef USER_PRINT 31deb5501aSWilliam A. Kennington III #define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__) 32deb5501aSWilliam A. Kennington III #endif 33deb5501aSWilliam A. Kennington III 345acaca2fSWilliam A. Kennington III // @func hash_init get ready to compute a hash 355acaca2fSWilliam A. Kennington III // 365acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct 375acaca2fSWilliam A. Kennington III // @param[in] hash_type - type of hash function to use 385acaca2fSWilliam A. Kennington III // 395acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success 405acaca2fSWilliam A. Kennington III 415acaca2fSWilliam A. Kennington III int hash_init(const void* ctx, enum hash_type type) 425acaca2fSWilliam A. Kennington III { 435acaca2fSWilliam A. Kennington III struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx; 445acaca2fSWilliam A. Kennington III struct hash_ctx* hash_context = (struct hash_ctx*)context->priv; 455acaca2fSWilliam A. Kennington III hash_context->hash_type = type; 465acaca2fSWilliam A. Kennington III if (type == HASH_SHA2_256) // SHA256_Init returns 1 475acaca2fSWilliam A. Kennington III SHA256_Init(&hash_context->sha256_ctx); 485acaca2fSWilliam A. Kennington III else if (type == HASH_SHA2_512) 495acaca2fSWilliam A. Kennington III SHA512_Init(&hash_context->sha512_ctx); 505acaca2fSWilliam A. Kennington III else 515acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 525acaca2fSWilliam A. Kennington III 535acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 545acaca2fSWilliam A. Kennington III } 555acaca2fSWilliam A. Kennington III 565acaca2fSWilliam A. Kennington III // @func hash_update add data to the hash 575acaca2fSWilliam A. Kennington III // 585acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct 595acaca2fSWilliam A. Kennington III // @param[in] buf - data to add to hash 605acaca2fSWilliam A. Kennington III // @param[in] count - number of bytes of data to add 615acaca2fSWilliam A. Kennington III // 625acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success 635acaca2fSWilliam A. Kennington III 645acaca2fSWilliam A. Kennington III int hash_update(void* ctx, const uint8_t* data, size_t size) 655acaca2fSWilliam A. Kennington III { 665acaca2fSWilliam A. Kennington III if (size == 0) 675acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 685acaca2fSWilliam A. Kennington III struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx; 695acaca2fSWilliam A. Kennington III struct hash_ctx* hash_context = (struct hash_ctx*)context->priv; 705acaca2fSWilliam A. Kennington III 715acaca2fSWilliam A. Kennington III if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1 725acaca2fSWilliam A. Kennington III SHA256_Update(&hash_context->sha256_ctx, data, size); 735acaca2fSWilliam A. Kennington III else if (hash_context->hash_type == HASH_SHA2_512) 745acaca2fSWilliam A. Kennington III SHA512_Update(&hash_context->sha512_ctx, data, size); 755acaca2fSWilliam A. Kennington III else 765acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 775acaca2fSWilliam A. Kennington III 785acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 795acaca2fSWilliam A. Kennington III } 805acaca2fSWilliam A. Kennington III 815acaca2fSWilliam A. Kennington III // @func hash_final finish hash calculation 825acaca2fSWilliam A. Kennington III // 835acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct 845acaca2fSWilliam A. Kennington III // @param[out] hash - buffer to write hash to (guaranteed to be big enough) 855acaca2fSWilliam A. Kennington III // 865acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success 875acaca2fSWilliam A. Kennington III 885acaca2fSWilliam A. Kennington III int hash_final(void* ctx, uint8_t* hash) 895acaca2fSWilliam A. Kennington III { 905acaca2fSWilliam A. Kennington III int rv; 915acaca2fSWilliam A. Kennington III struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx; 925acaca2fSWilliam A. Kennington III struct hash_ctx* hash_context = (struct hash_ctx*)context->priv; 935acaca2fSWilliam A. Kennington III 945acaca2fSWilliam A. Kennington III if (hash_context->hash_type == HASH_SHA2_256) 955acaca2fSWilliam A. Kennington III rv = SHA256_Final(hash, &hash_context->sha256_ctx); 965acaca2fSWilliam A. Kennington III else if (hash_context->hash_type == HASH_SHA2_512) 975acaca2fSWilliam A. Kennington III rv = SHA512_Final(hash, &hash_context->sha512_ctx); 985acaca2fSWilliam A. Kennington III else 995acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 1005acaca2fSWilliam A. Kennington III 1015acaca2fSWilliam A. Kennington III if (rv) 1025acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 1035acaca2fSWilliam A. Kennington III else 1045acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 1055acaca2fSWilliam A. Kennington III } 1065acaca2fSWilliam A. Kennington III 1075acaca2fSWilliam A. Kennington III // @func verify check that the signature is valid for given hashed data 1085acaca2fSWilliam A. Kennington III // 1095acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct 1105acaca2fSWilliam A. Kennington III // @param[in] scheme - type of signature, hash, etc. 1115acaca2fSWilliam A. Kennington III // @param[in] sig - signature blob 1125acaca2fSWilliam A. Kennington III // @param[in] sig_len - length of signature in bytes 1135acaca2fSWilliam A. Kennington III // @param[in] data - pre-hashed data to verify 1145acaca2fSWilliam A. Kennington III // @param[in] data_len - length of hashed data in bytes 1155acaca2fSWilliam A. Kennington III // 1165acaca2fSWilliam A. Kennington III // verify_signature expects RSA public key file path in ctx->key_ring 1175acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success 1185acaca2fSWilliam A. Kennington III 1195acaca2fSWilliam A. Kennington III int verify_signature(const void* ctx, enum signature_scheme sig_scheme, 1205acaca2fSWilliam A. Kennington III const uint8_t* sig, size_t sig_len, 1215acaca2fSWilliam A. Kennington III const uint8_t* data, size_t data_len) 1225acaca2fSWilliam A. Kennington III { 1235acaca2fSWilliam A. Kennington III // By default returns error. 1245acaca2fSWilliam A. Kennington III int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT; 1255acaca2fSWilliam A. Kennington III 126af46bea6SWilliam A. Kennington III CPRINTS(ctx, "sig_len %zu sig: ", sig_len); 127deb5501aSWilliam A. Kennington III for (size_t i = 0; i < sig_len; i++) 1285acaca2fSWilliam A. Kennington III { 129deb5501aSWilliam A. Kennington III CPRINTS(ctx, "%x", sig[i]); 1305acaca2fSWilliam A. Kennington III } 131af46bea6SWilliam A. Kennington III CPRINTS(ctx, "\n"); 1325acaca2fSWilliam A. Kennington III 1335acaca2fSWilliam A. Kennington III struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx; 1345acaca2fSWilliam A. Kennington III FILE* fp = fopen(lctx->keyring, "r"); 1355acaca2fSWilliam A. Kennington III RSA *rsa = NULL, *pub_rsa = NULL; 1365acaca2fSWilliam A. Kennington III EVP_PKEY* pkey = NULL; 1375acaca2fSWilliam A. Kennington III BIO* bio = BIO_new(BIO_s_mem()); 1385acaca2fSWilliam A. Kennington III if (!fp) 1395acaca2fSWilliam A. Kennington III { 140af46bea6SWilliam A. Kennington III CPRINTS(ctx, "fopen failed\n"); 1415acaca2fSWilliam A. Kennington III goto clean_up; 1425acaca2fSWilliam A. Kennington III } 1435acaca2fSWilliam A. Kennington III 1445acaca2fSWilliam A. Kennington III pkey = PEM_read_PUBKEY(fp, 0, 0, 0); 1455acaca2fSWilliam A. Kennington III if (!pkey) 1465acaca2fSWilliam A. Kennington III { 147af46bea6SWilliam A. Kennington III CPRINTS(ctx, "Read public key failed\n"); 1485acaca2fSWilliam A. Kennington III goto clean_up; 1495acaca2fSWilliam A. Kennington III } 1505acaca2fSWilliam A. Kennington III 1515acaca2fSWilliam A. Kennington III rsa = EVP_PKEY_get1_RSA(pkey); 1525acaca2fSWilliam A. Kennington III if (!rsa) 1535acaca2fSWilliam A. Kennington III { 1545acaca2fSWilliam A. Kennington III goto clean_up; 1555acaca2fSWilliam A. Kennington III } 1565acaca2fSWilliam A. Kennington III pub_rsa = RSAPublicKey_dup(rsa); 1575acaca2fSWilliam A. Kennington III if (!RSA_print(bio, pub_rsa, 2)) 1585acaca2fSWilliam A. Kennington III { 159af46bea6SWilliam A. Kennington III CPRINTS(ctx, "RSA print failed\n"); 1605acaca2fSWilliam A. Kennington III } 1615acaca2fSWilliam A. Kennington III if (!pub_rsa) 1625acaca2fSWilliam A. Kennington III { 163af46bea6SWilliam A. Kennington III CPRINTS(ctx, "no pub RSA\n"); 1645acaca2fSWilliam A. Kennington III goto clean_up; 1655acaca2fSWilliam A. Kennington III } 166af46bea6SWilliam A. Kennington III CPRINTS(ctx, "public RSA\n"); 1675acaca2fSWilliam A. Kennington III char buffer[1024]; 1685acaca2fSWilliam A. Kennington III while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0) 1695acaca2fSWilliam A. Kennington III { 170deb5501aSWilliam A. Kennington III CPRINTS(ctx, " %s", buffer); 1715acaca2fSWilliam A. Kennington III } 1725acaca2fSWilliam A. Kennington III enum hash_type hash_type; 1735acaca2fSWilliam A. Kennington III rv = get_hash_type_from_signature(sig_scheme, &hash_type); 1745acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 1755acaca2fSWilliam A. Kennington III { 176af46bea6SWilliam A. Kennington III CPRINTS(ctx, "Invalid hash_type!\n"); 1775acaca2fSWilliam A. Kennington III goto clean_up; 1785acaca2fSWilliam A. Kennington III } 1795acaca2fSWilliam A. Kennington III int hash_nid = -1; 1805acaca2fSWilliam A. Kennington III if (hash_type == HASH_SHA2_256) 1815acaca2fSWilliam A. Kennington III { 1825acaca2fSWilliam A. Kennington III hash_nid = NID_sha256; 1835acaca2fSWilliam A. Kennington III } 1845acaca2fSWilliam A. Kennington III else if (hash_type == HASH_SHA2_512) 1855acaca2fSWilliam A. Kennington III { 1865acaca2fSWilliam A. Kennington III hash_nid = NID_sha512; 1875acaca2fSWilliam A. Kennington III } 1885acaca2fSWilliam A. Kennington III else 1895acaca2fSWilliam A. Kennington III { 1905acaca2fSWilliam A. Kennington III rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 1915acaca2fSWilliam A. Kennington III goto clean_up; 1925acaca2fSWilliam A. Kennington III } 1935acaca2fSWilliam A. Kennington III 1945acaca2fSWilliam A. Kennington III int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa); 1955acaca2fSWilliam A. Kennington III // OpenSSL RSA_verify returns 1 on success and 0 on failure 1965acaca2fSWilliam A. Kennington III if (!ret) 1975acaca2fSWilliam A. Kennington III { 198af46bea6SWilliam A. Kennington III CPRINTS(ctx, "OPENSSL_ERROR: %s\n", 1995acaca2fSWilliam A. Kennington III ERR_error_string(ERR_get_error(), NULL)); 2005acaca2fSWilliam A. Kennington III rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 2015acaca2fSWilliam A. Kennington III goto clean_up; 2025acaca2fSWilliam A. Kennington III } 2035acaca2fSWilliam A. Kennington III rv = LIBCR51SIGN_SUCCESS; 204af46bea6SWilliam A. Kennington III CPRINTS(ctx, "sig: "); 205deb5501aSWilliam A. Kennington III for (size_t i = 0; i < sig_len; i++) 2065acaca2fSWilliam A. Kennington III { 207deb5501aSWilliam A. Kennington III CPRINTS(ctx, "%x", sig[i]); 2085acaca2fSWilliam A. Kennington III } 209af46bea6SWilliam A. Kennington III CPRINTS(ctx, "\n"); 2105acaca2fSWilliam A. Kennington III 211af46bea6SWilliam A. Kennington III CPRINTS(ctx, "data: "); 212deb5501aSWilliam A. Kennington III for (size_t i = 0; i < data_len; i++) 2135acaca2fSWilliam A. Kennington III { 214deb5501aSWilliam A. Kennington III CPRINTS(ctx, "%x", data[i]); 2155acaca2fSWilliam A. Kennington III } 216af46bea6SWilliam A. Kennington III CPRINTS(ctx, "\n"); 217af46bea6SWilliam A. Kennington III 2185acaca2fSWilliam A. Kennington III const unsigned rsa_size = RSA_size(pub_rsa); 219af46bea6SWilliam A. Kennington III CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len); 2205acaca2fSWilliam A. Kennington III 2215acaca2fSWilliam A. Kennington III clean_up: 2225acaca2fSWilliam A. Kennington III if (fp) 2235acaca2fSWilliam A. Kennington III { 2245acaca2fSWilliam A. Kennington III fclose(fp); 2255acaca2fSWilliam A. Kennington III } 2265acaca2fSWilliam A. Kennington III EVP_PKEY_free(pkey); 2275acaca2fSWilliam A. Kennington III RSA_free(rsa); 2285acaca2fSWilliam A. Kennington III RSA_free(pub_rsa); 2295acaca2fSWilliam A. Kennington III BIO_free(bio); 2305acaca2fSWilliam A. Kennington III return rv; 2315acaca2fSWilliam A. Kennington III } 2325acaca2fSWilliam A. Kennington III 2335acaca2fSWilliam A. Kennington III #ifdef __cplusplus 2345acaca2fSWilliam A. Kennington III } // extern "C" 2355acaca2fSWilliam A. Kennington III #endif 236