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