| /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include <openssl/pem.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| #include "2common.h" |
| #include "2rsa.h" |
| #include "2sha.h" |
| #include "2sysincludes.h" |
| #include "host_common.h" |
| #include "host_signature21.h" |
| #include "signature_digest.h" |
| |
| uint8_t* PrependDigestInfo(enum vb2_hash_algorithm hash_alg, uint8_t* digest) |
| { |
| const int digest_size = vb2_digest_size(hash_alg); |
| uint32_t digestinfo_size = 0; |
| const uint8_t* digestinfo = NULL; |
| |
| if (VB2_SUCCESS != vb2_digest_info(hash_alg, &digestinfo, |
| &digestinfo_size)) |
| return NULL; |
| |
| uint8_t* p = malloc(digestinfo_size + digest_size); |
| memcpy(p, digestinfo, digestinfo_size); |
| memcpy(p + digestinfo_size, digest, digest_size); |
| return p; |
| } |
| |
| uint8_t* SignatureDigest(const uint8_t* buf, uint64_t len, |
| unsigned int algorithm) |
| { |
| uint8_t* info_digest = NULL; |
| |
| uint8_t digest[VB2_SHA512_DIGEST_SIZE]; /* Longest digest */ |
| enum vb2_hash_algorithm hash_alg; |
| |
| if (algorithm >= VB2_ALG_COUNT) { |
| fprintf(stderr, |
| "SignatureDigest(): Called with invalid algorithm!\n"); |
| return NULL; |
| } |
| |
| hash_alg = vb2_crypto_to_hash(algorithm); |
| |
| if (VB2_SUCCESS == vb2_digest_buffer(buf, len, hash_alg, |
| digest, sizeof(digest))) { |
| info_digest = PrependDigestInfo(hash_alg, digest); |
| } |
| return info_digest; |
| } |
| |
| uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file, |
| unsigned int algorithm) |
| { |
| const enum vb2_hash_algorithm hash_alg = vb2_crypto_to_hash(algorithm); |
| FILE* key_fp = NULL; |
| RSA* key = NULL; |
| uint8_t* signature = NULL; |
| uint8_t* signature_digest = SignatureDigest(buf, len, algorithm); |
| if (!signature_digest) { |
| fprintf(stderr, "SignatureBuf(): " |
| "Couldn't get signature digest\n"); |
| return NULL; |
| } |
| |
| const int digest_size = vb2_digest_size(hash_alg); |
| |
| uint32_t digestinfo_size = 0; |
| const uint8_t* digestinfo = NULL; |
| if (VB2_SUCCESS != vb2_digest_info(hash_alg, &digestinfo, |
| &digestinfo_size)) { |
| fprintf(stderr, "SignatureBuf(): Couldn't get digest info\n"); |
| free(signature_digest); |
| return NULL; |
| } |
| |
| int signature_digest_len = digest_size + digestinfo_size; |
| |
| key_fp = fopen(key_file, "r"); |
| if (!key_fp) { |
| fprintf(stderr, "SignatureBuf(): Couldn't open key file: %s\n", |
| key_file); |
| free(signature_digest); |
| return NULL; |
| } |
| if ((key = PEM_read_RSAPrivateKey(key_fp, NULL, NULL, NULL))) |
| signature = (uint8_t *)malloc( |
| vb2_rsa_sig_size(vb2_crypto_to_signature(algorithm))); |
| else |
| fprintf(stderr, "SignatureBuf(): " |
| "Couldn't read private key from: %s\n", key_file); |
| if (signature) { |
| if (-1 == RSA_private_encrypt( |
| signature_digest_len, /* Input length. */ |
| signature_digest, /* Input data. */ |
| signature, /* Output signature. */ |
| key, /* Key to use. */ |
| RSA_PKCS1_PADDING)) /* Padding to use. */ |
| fprintf(stderr, "SignatureBuf(): " |
| "RSA_private_encrypt() failed.\n"); |
| } |
| fclose(key_fp); |
| if (key) |
| RSA_free(key); |
| free(signature_digest); |
| return signature; |
| } |