summaryrefslogtreecommitdiff
path: root/host/lib/signature_digest.c
blob: b56233a030d57f93303b9dce8f3e148d050afcc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/* 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 "2sysincludes.h"

#include "2common.h"
#include "2sha.h"
#include "cryptolib.h"
#include "host_common.h"
#include "signature_digest.h"


uint8_t* PrependDigestInfo(unsigned int algorithm, uint8_t* digest) {
  const int digest_size = vb2_digest_size(vb2_crypto_to_hash(algorithm));
  const int digestinfo_size = digestinfo_size_map[algorithm];
  const uint8_t* digestinfo = hash_digestinfo_map[algorithm];
  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 */

  if (algorithm >= kNumAlgorithms) {
    VBDEBUG(("SignatureDigest() called with invalid algorithm!\n"));
  } else if (VB2_SUCCESS == vb2_digest_buffer(buf, len,
					      vb2_crypto_to_hash(algorithm),
					      digest, sizeof(digest))) {
    info_digest = PrependDigestInfo(algorithm, digest);
  }
  return info_digest;
}

uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file,
                      unsigned int algorithm) {
  FILE* key_fp = NULL;
  RSA* key = NULL;
  uint8_t* signature = NULL;
  uint8_t* signature_digest = SignatureDigest(buf, len, algorithm);
  const int digest_size = vb2_digest_size(vb2_crypto_to_hash(algorithm));
  int signature_digest_len = (digest_size + digestinfo_size_map[algorithm]);
  key_fp  = fopen(key_file, "r");
  if (!key_fp) {
    VBDEBUG(("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(siglen_map[algorithm]);
  else
    VBDEBUG(("SignatureBuf(): Couldn't read private key from file: %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. */
      VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n"));
  }
  fclose(key_fp);
  if (key)
    RSA_free(key);
  free(signature_digest);
  return signature;
}