Coverage Report

Created: 2024-11-21 07:03

/src/trezor-firmware/crypto/hmac_drbg.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (c) 2019 Andrew R. Kozlik
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included
12
 * in all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
18
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 * OTHER DEALINGS IN THE SOFTWARE.
21
 */
22
23
#include "hmac_drbg.h"
24
#include <string.h>
25
#include "memzero.h"
26
#include "sha2.h"
27
28
static void update_k(HMAC_DRBG_CTX *ctx, uint8_t domain, const uint8_t *data1,
29
609
                     size_t len1, const uint8_t *data2, size_t len2) {
30
  // Computes K = HMAC(K, V || domain || data1 || data 2).
31
32
  // First hash operation of HMAC.
33
609
  uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
34
609
  if (len1 + len2 == 0) {
35
203
    ctx->v[8] = 0x00800000;
36
203
    ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
37
203
    sha256_Transform(ctx->idig, ctx->v, h);
38
203
    ctx->v[8] = 0x80000000;
39
203
    ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
40
406
  } else {
41
406
    SHA256_CTX sha_ctx = {0};
42
406
    memcpy(sha_ctx.state, ctx->idig, SHA256_DIGEST_LENGTH);
43
3.65k
    for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++) {
44
3.24k
#if BYTE_ORDER == LITTLE_ENDIAN
45
3.24k
      REVERSE32(ctx->v[i], sha_ctx.buffer[i]);
46
#else
47
      sha_ctx.buffer[i] = ctx->v[i];
48
#endif
49
3.24k
    }
50
406
    ((uint8_t *)sha_ctx.buffer)[SHA256_DIGEST_LENGTH] = domain;
51
406
    sha_ctx.bitcount = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
52
406
    sha256_Update(&sha_ctx, data1, len1);
53
406
    sha256_Update(&sha_ctx, data2, len2);
54
406
    sha256_Final(&sha_ctx, (uint8_t *)h);
55
406
#if BYTE_ORDER == LITTLE_ENDIAN
56
3.65k
    for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++)
57
3.24k
      REVERSE32(h[i], h[i]);
58
406
#endif
59
406
  }
60
61
  // Second hash operation of HMAC.
62
609
  h[8] = 0x80000000;
63
609
  h[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
64
609
  sha256_Transform(ctx->odig, h, h);
65
66
  // Precompute the inner digest and outer digest of K.
67
609
  h[8] = 0;
68
609
  h[15] = 0;
69
10.3k
  for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
70
9.74k
    h[i] ^= 0x36363636;
71
9.74k
  }
72
609
  sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
73
74
10.3k
  for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
75
9.74k
    h[i] = h[i] ^ 0x36363636 ^ 0x5c5c5c5c;
76
9.74k
  }
77
609
  sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
78
609
  memzero(h, sizeof(h));
79
609
}
80
81
812
static void update_v(HMAC_DRBG_CTX *ctx) {
82
812
  sha256_Transform(ctx->idig, ctx->v, ctx->v);
83
812
  sha256_Transform(ctx->odig, ctx->v, ctx->v);
84
812
}
85
86
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *entropy,
87
                    size_t entropy_len, const uint8_t *nonce,
88
203
                    size_t nonce_len) {
89
203
  uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
90
91
  // Precompute the inner digest and outer digest of K = 0x00 ... 0x00.
92
203
  memset(h, 0x36, sizeof(h));
93
203
  sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
94
203
  memset(h, 0x5c, sizeof(h));
95
203
  sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
96
97
  // Let V = 0x01 ... 0x01.
98
203
  memset(ctx->v, 1, SHA256_DIGEST_LENGTH);
99
1.42k
  for (size_t i = 9; i < 15; i++) ctx->v[i] = 0;
100
203
  ctx->v[8] = 0x80000000;
101
203
  ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
102
103
203
  hmac_drbg_reseed(ctx, entropy, entropy_len, nonce, nonce_len);
104
105
203
  memzero(h, sizeof(h));
106
203
}
107
108
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *entropy, size_t len,
109
203
                      const uint8_t *addin, size_t addin_len) {
110
203
  update_k(ctx, 0, entropy, len, addin, addin_len);
111
203
  update_v(ctx);
112
203
  if (len == 0) return;
113
203
  update_k(ctx, 1, entropy, len, addin, addin_len);
114
203
  update_v(ctx);
115
203
}
116
117
203
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len) {
118
203
  size_t i = 0;
119
406
  while (i < len) {
120
203
    update_v(ctx);
121
1.82k
    for (size_t j = 0; j < 8 && i < len; j++) {
122
1.62k
      uint32_t r = ctx->v[j];
123
8.12k
      for (int k = 24; k >= 0 && i < len; k -= 8) {
124
6.49k
        buf[i++] = (r >> k) & 0xFF;
125
6.49k
      }
126
1.62k
    }
127
203
  }
128
203
  update_k(ctx, 0, NULL, 0, NULL, 0);
129
203
  update_v(ctx);
130
203
}