1 /* 2 * Copyright 2021 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <libcr51sign/libcr51sign_support.h> 17 #include <openssl/err.h> 18 #include <openssl/evp.h> 19 #include <openssl/pem.h> 20 #include <openssl/rsa.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 #ifdef __cplusplus 25 extern "C" 26 { 27 #endif 28 29 #ifndef USER_PRINT 30 #define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__) 31 #endif 32 33 // @func hash_init get ready to compute a hash 34 // 35 // @param[in] ctx - context struct 36 // @param[in] hash_type - type of hash function to use 37 // 38 // @return nonzero on error, zero on success 39 40 int hash_init(const void* ctx, enum hash_type type) 41 { 42 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx; 43 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv; 44 hash_context->hash_type = type; 45 if (type == HASH_SHA2_256) // SHA256_Init returns 1 46 SHA256_Init(&hash_context->sha256_ctx); 47 else if (type == HASH_SHA2_512) 48 SHA512_Init(&hash_context->sha512_ctx); 49 else 50 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 51 52 return LIBCR51SIGN_SUCCESS; 53 } 54 55 // @func hash_update add data to the hash 56 // 57 // @param[in] ctx - context struct 58 // @param[in] buf - data to add to hash 59 // @param[in] count - number of bytes of data to add 60 // 61 // @return nonzero on error, zero on success 62 63 int hash_update(void* ctx, const uint8_t* data, size_t size) 64 { 65 if (size == 0) 66 return LIBCR51SIGN_SUCCESS; 67 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx; 68 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv; 69 70 if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1 71 SHA256_Update(&hash_context->sha256_ctx, data, size); 72 else if (hash_context->hash_type == HASH_SHA2_512) 73 SHA512_Update(&hash_context->sha512_ctx, data, size); 74 else 75 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 76 77 return LIBCR51SIGN_SUCCESS; 78 } 79 80 // @func hash_final finish hash calculation 81 // 82 // @param[in] ctx - context struct 83 // @param[out] hash - buffer to write hash to (guaranteed to be big enough) 84 // 85 // @return nonzero on error, zero on success 86 87 int hash_final(void* ctx, uint8_t* hash) 88 { 89 int rv; 90 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx; 91 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv; 92 93 if (hash_context->hash_type == HASH_SHA2_256) 94 rv = SHA256_Final(hash, &hash_context->sha256_ctx); 95 else if (hash_context->hash_type == HASH_SHA2_512) 96 rv = SHA512_Final(hash, &hash_context->sha512_ctx); 97 else 98 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 99 100 if (rv) 101 return LIBCR51SIGN_SUCCESS; 102 else 103 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 104 } 105 106 // @func verify check that the signature is valid for given hashed data 107 // 108 // @param[in] ctx - context struct 109 // @param[in] scheme - type of signature, hash, etc. 110 // @param[in] sig - signature blob 111 // @param[in] sig_len - length of signature in bytes 112 // @param[in] data - pre-hashed data to verify 113 // @param[in] data_len - length of hashed data in bytes 114 // 115 // verify_signature expects RSA public key file path in ctx->key_ring 116 // @return nonzero on error, zero on success 117 118 int verify_signature(const void* ctx, enum signature_scheme sig_scheme, 119 const uint8_t* sig, size_t sig_len, 120 const uint8_t* data, size_t data_len) 121 { 122 // By default returns error. 123 int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT; 124 125 CPRINTS(ctx, "sig_len %zu sig: ", sig_len); 126 for (size_t i = 0; i < sig_len; i++) 127 { 128 CPRINTS(ctx, "%x", sig[i]); 129 } 130 CPRINTS(ctx, "\n"); 131 132 struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx; 133 FILE* fp = fopen(lctx->keyring, "r"); 134 RSA *rsa = NULL, *pub_rsa = NULL; 135 EVP_PKEY* pkey = NULL; 136 BIO* bio = BIO_new(BIO_s_mem()); 137 if (!fp) 138 { 139 CPRINTS(ctx, "fopen failed\n"); 140 goto clean_up; 141 } 142 143 pkey = PEM_read_PUBKEY(fp, 0, 0, 0); 144 if (!pkey) 145 { 146 CPRINTS(ctx, "Read public key failed\n"); 147 goto clean_up; 148 } 149 150 rsa = EVP_PKEY_get1_RSA(pkey); 151 if (!rsa) 152 { 153 goto clean_up; 154 } 155 pub_rsa = RSAPublicKey_dup(rsa); 156 if (!RSA_print(bio, pub_rsa, 2)) 157 { 158 CPRINTS(ctx, "RSA print failed\n"); 159 } 160 if (!pub_rsa) 161 { 162 CPRINTS(ctx, "no pub RSA\n"); 163 goto clean_up; 164 } 165 CPRINTS(ctx, "public RSA\n"); 166 char buffer[1024]; 167 while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0) 168 { 169 CPRINTS(ctx, " %s", buffer); 170 } 171 enum hash_type hash_type; 172 rv = get_hash_type_from_signature(sig_scheme, &hash_type); 173 if (rv != LIBCR51SIGN_SUCCESS) 174 { 175 CPRINTS(ctx, "Invalid hash_type!\n"); 176 goto clean_up; 177 } 178 int hash_nid = -1; 179 if (hash_type == HASH_SHA2_256) 180 { 181 hash_nid = NID_sha256; 182 } 183 else if (hash_type == HASH_SHA2_512) 184 { 185 hash_nid = NID_sha512; 186 } 187 else 188 { 189 rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 190 goto clean_up; 191 } 192 193 int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa); 194 // OpenSSL RSA_verify returns 1 on success and 0 on failure 195 if (!ret) 196 { 197 CPRINTS(ctx, "OPENSSL_ERROR: %s\n", 198 ERR_error_string(ERR_get_error(), NULL)); 199 rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 200 goto clean_up; 201 } 202 rv = LIBCR51SIGN_SUCCESS; 203 CPRINTS(ctx, "sig: "); 204 for (size_t i = 0; i < sig_len; i++) 205 { 206 CPRINTS(ctx, "%x", sig[i]); 207 } 208 CPRINTS(ctx, "\n"); 209 210 CPRINTS(ctx, "data: "); 211 for (size_t i = 0; i < data_len; i++) 212 { 213 CPRINTS(ctx, "%x", data[i]); 214 } 215 CPRINTS(ctx, "\n"); 216 217 const unsigned rsa_size = RSA_size(pub_rsa); 218 CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len); 219 220 clean_up: 221 if (fp) 222 { 223 fclose(fp); 224 } 225 EVP_PKEY_free(pkey); 226 RSA_free(rsa); 227 RSA_free(pub_rsa); 228 BIO_free(bio); 229 return rv; 230 } 231 232 #ifdef __cplusplus 233 } // extern "C" 234 #endif 235