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