Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 1 | /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 | * Use of this source code is governed by a BSD-style license that can be |
| 3 | * found in the LICENSE file. |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | #include "signature_digest.h" |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 7 | #define OPENSSL_NO_SHA |
| 8 | #include <openssl/engine.h> |
| 9 | #include <openssl/pem.h> |
| 10 | #include <openssl/rsa.h> |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 11 | |
| 12 | #include <stdio.h> |
| 13 | #include <stdlib.h> |
| 14 | #include <unistd.h> |
| 15 | |
Gaurav Shah | 5411c7a | 2010-03-31 10:56:49 -0700 | [diff] [blame] | 16 | #include "cryptolib.h" |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 17 | #include "host_common.h" |
| 18 | |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 19 | |
Gaurav Shah | 47b593d | 2010-08-17 15:48:22 -0700 | [diff] [blame] | 20 | uint8_t* PrependDigestInfo(unsigned int algorithm, uint8_t* digest) { |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 21 | const int digest_size = hash_size_map[algorithm]; |
| 22 | const int digestinfo_size = digestinfo_size_map[algorithm]; |
| 23 | const uint8_t* digestinfo = hash_digestinfo_map[algorithm]; |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 24 | uint8_t* p = malloc(digestinfo_size + digest_size); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 25 | Memcpy(p, digestinfo, digestinfo_size); |
| 26 | Memcpy(p + digestinfo_size, digest, digest_size); |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 27 | return p; |
| 28 | } |
| 29 | |
Gaurav Shah | 47b593d | 2010-08-17 15:48:22 -0700 | [diff] [blame] | 30 | uint8_t* SignatureDigest(const uint8_t* buf, uint64_t len, |
| 31 | unsigned int algorithm) { |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 32 | uint8_t* info_digest = NULL; |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 33 | uint8_t* digest = NULL; |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 34 | |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 35 | if (algorithm >= kNumAlgorithms) { |
Bill Richardson | abf0550 | 2010-07-01 10:22:06 -0700 | [diff] [blame] | 36 | VBDEBUG(("SignatureDigest() called with invalid algorithm!\n")); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 37 | } else if ((digest = DigestBuf(buf, len, algorithm))) { |
| 38 | info_digest = PrependDigestInfo(algorithm, digest); |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 39 | } |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 40 | free(digest); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 41 | return info_digest; |
| 42 | } |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 43 | |
Gaurav Shah | 456678b | 2010-03-10 18:38:45 -0800 | [diff] [blame] | 44 | uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file, |
Gaurav Shah | 47b593d | 2010-08-17 15:48:22 -0700 | [diff] [blame] | 45 | unsigned int algorithm) { |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 46 | FILE* key_fp = NULL; |
| 47 | RSA* key = NULL; |
| 48 | uint8_t* signature = NULL; |
| 49 | uint8_t* signature_digest = SignatureDigest(buf, len, algorithm); |
| 50 | int signature_digest_len = (hash_size_map[algorithm] + |
| 51 | digestinfo_size_map[algorithm]); |
| 52 | key_fp = fopen(key_file, "r"); |
| 53 | if (!key_fp) { |
Bill Richardson | abf0550 | 2010-07-01 10:22:06 -0700 | [diff] [blame] | 54 | VBDEBUG(("SignatureBuf(): Couldn't open key file: %s\n", key_file)); |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 55 | free(signature_digest); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 56 | return NULL; |
| 57 | } |
| 58 | if ((key = PEM_read_RSAPrivateKey(key_fp, NULL, NULL, NULL))) |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 59 | signature = (uint8_t*) malloc(siglen_map[algorithm]); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 60 | else |
Bill Richardson | abf0550 | 2010-07-01 10:22:06 -0700 | [diff] [blame] | 61 | VBDEBUG(("SignatureBuf(): Couldn't read private key from file: %s\n", |
| 62 | key_file)); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 63 | if (signature) { |
| 64 | if (-1 == RSA_private_encrypt(signature_digest_len, /* Input length. */ |
| 65 | signature_digest, /* Input data. */ |
| 66 | signature, /* Output signature. */ |
| 67 | key, /* Key to use. */ |
| 68 | RSA_PKCS1_PADDING)) /* Padding to use. */ |
Bill Richardson | abf0550 | 2010-07-01 10:22:06 -0700 | [diff] [blame] | 69 | VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n")); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 70 | } |
Gaurav Shah | 259de40 | 2010-03-12 17:42:03 -0800 | [diff] [blame] | 71 | fclose(key_fp); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 72 | if (key) |
| 73 | RSA_free(key); |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 74 | free(signature_digest); |
Gaurav Shah | f5564fa | 2010-03-02 15:40:01 -0800 | [diff] [blame] | 75 | return signature; |
Gaurav Shah | 8bf29d8 | 2010-01-28 19:43:24 -0800 | [diff] [blame] | 76 | } |