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.
4  */
5 
6 #include <openssl/pem.h>
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 
12 #include "cryptolib.h"
13 #include "host_common.h"
14 #include "signature_digest.h"
15 
16 
PrependDigestInfo(unsigned int algorithm,uint8_t * digest)17 uint8_t* PrependDigestInfo(unsigned int algorithm, uint8_t* digest) {
18   const int digest_size = hash_size_map[algorithm];
19   const int digestinfo_size = digestinfo_size_map[algorithm];
20   const uint8_t* digestinfo = hash_digestinfo_map[algorithm];
21   uint8_t* p = malloc(digestinfo_size + digest_size);
22   Memcpy(p, digestinfo, digestinfo_size);
23   Memcpy(p + digestinfo_size, digest, digest_size);
24   return p;
25 }
26 
SignatureDigest(const uint8_t * buf,uint64_t len,unsigned int algorithm)27 uint8_t* SignatureDigest(const uint8_t* buf, uint64_t len,
28                          unsigned int algorithm) {
29   uint8_t* info_digest  = NULL;
30   uint8_t* digest = NULL;
31 
32   if (algorithm >= kNumAlgorithms) {
33     VBDEBUG(("SignatureDigest() called with invalid algorithm!\n"));
34   } else if ((digest = DigestBuf(buf, len, algorithm))) {
35     info_digest = PrependDigestInfo(algorithm, digest);
36   }
37   free(digest);
38   return info_digest;
39 }
40 
SignatureBuf(const uint8_t * buf,uint64_t len,const char * key_file,unsigned int algorithm)41 uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file,
42                       unsigned int algorithm) {
43   FILE* key_fp = NULL;
44   RSA* key = NULL;
45   uint8_t* signature = NULL;
46   uint8_t* signature_digest = SignatureDigest(buf, len, algorithm);
47   int signature_digest_len = (hash_size_map[algorithm] +
48                               digestinfo_size_map[algorithm]);
49   key_fp  = fopen(key_file, "r");
50   if (!key_fp) {
51     VBDEBUG(("SignatureBuf(): Couldn't open key file: %s\n", key_file));
52     free(signature_digest);
53     return NULL;
54   }
55   if ((key = PEM_read_RSAPrivateKey(key_fp, NULL, NULL, NULL)))
56     signature = (uint8_t*) malloc(siglen_map[algorithm]);
57   else
58     VBDEBUG(("SignatureBuf(): Couldn't read private key from file: %s\n",
59              key_file));
60   if (signature) {
61     if (-1 == RSA_private_encrypt(signature_digest_len,  /* Input length. */
62                                   signature_digest,  /* Input data. */
63                                   signature,  /* Output signature. */
64                                   key,  /* Key to use. */
65                                   RSA_PKCS1_PADDING))  /* Padding to use. */
66       VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n"));
67   }
68   fclose(key_fp);
69   if (key)
70     RSA_free(key);
71   free(signature_digest);
72   return signature;
73 }
74