Software APIs
rsa_encryption.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/lib/crypto/impl/rsa/rsa_encryption.h"
6 
10 #include "sw/device/lib/crypto/drivers/entropy.h"
11 #include "sw/device/lib/crypto/impl/rsa/rsa_modexp.h"
12 #include "sw/device/lib/crypto/impl/rsa/rsa_padding.h"
14 
15 // Module ID for status codes.
16 #define MODULE_ID MAKE_MODULE_ID('r', 'e', 'n')
17 
18 status_t rsa_encrypt_2048_start(const rsa_2048_public_key_t *public_key,
19  const otcrypto_hash_mode_t hash_mode,
20  const uint8_t *message, size_t message_bytelen,
21  const uint8_t *label, size_t label_bytelen) {
22  // Encode the message.
23  rsa_2048_int_t encoded_message;
24  HARDENED_TRY(rsa_padding_oaep_encode(
25  hash_mode, message, message_bytelen, label, label_bytelen,
26  ARRAYSIZE(encoded_message.data), encoded_message.data));
27 
28  // Start computing (encoded_message ^ e) mod n with a variable-time
29  // exponentiation.
30  return rsa_modexp_vartime_2048_start(&encoded_message, public_key->e,
31  &public_key->n);
32 }
33 
34 status_t rsa_encrypt_2048_finalize(rsa_2048_int_t *ciphertext) {
35  return rsa_modexp_2048_finalize(ciphertext);
36 }
37 
38 status_t rsa_decrypt_2048_start(const rsa_2048_private_key_t *private_key,
39  const rsa_2048_int_t *ciphertext) {
40  // Start computing (ciphertext ^ d) mod n.
41  return rsa_modexp_consttime_2048_start(ciphertext, &private_key->d,
42  &private_key->n);
43 }
44 
45 status_t rsa_decrypt_finalize(const otcrypto_hash_mode_t hash_mode,
46  const uint8_t *label, size_t label_bytelen,
47  size_t plaintext_max_wordlen, uint8_t *plaintext,
48  size_t *plaintext_len) {
49  // Wait for OTBN to complete and get the size for the last RSA operation.
50  size_t num_words;
51  HARDENED_TRY(rsa_modexp_wait(&num_words));
52 
53  // Guard against overflow in the plaintext length checks.
54  if (plaintext_max_wordlen > UINT32_MAX / sizeof(uint32_t)) {
55  return OTCRYPTO_BAD_ARGS;
56  }
57 
58  // Check that enough space has been allocated for the plaintext.
59  size_t max_plaintext_bytelen = 0;
60  HARDENED_TRY(rsa_padding_oaep_max_message_bytelen(hash_mode, num_words,
61  &max_plaintext_bytelen));
62  if (plaintext_max_wordlen <
63  ceil_div(max_plaintext_bytelen, sizeof(uint32_t))) {
64  return OTCRYPTO_BAD_ARGS;
65  }
66  HARDENED_CHECK_GE(plaintext_max_wordlen * sizeof(uint32_t),
67  max_plaintext_bytelen);
68 
69  // Call the appropriate `finalize()` operation to get the recovered encoded
70  // message.
71  switch (num_words) {
72  case kRsa2048NumWords: {
73  rsa_2048_int_t recovered_message;
74  HARDENED_TRY(rsa_modexp_2048_finalize(&recovered_message));
75  return rsa_padding_oaep_decode(
76  hash_mode, label, label_bytelen, recovered_message.data,
77  ARRAYSIZE(recovered_message.data), plaintext, plaintext_len);
78  }
79  case kRsa3072NumWords: {
80  rsa_3072_int_t recovered_message;
81  HARDENED_TRY(rsa_modexp_3072_finalize(&recovered_message));
82  return rsa_padding_oaep_decode(
83  hash_mode, label, label_bytelen, recovered_message.data,
84  ARRAYSIZE(recovered_message.data), plaintext, plaintext_len);
85  }
86  case kRsa4096NumWords: {
87  rsa_4096_int_t recovered_message;
88  HARDENED_TRY(rsa_modexp_4096_finalize(&recovered_message));
89  return rsa_padding_oaep_decode(
90  hash_mode, label, label_bytelen, recovered_message.data,
91  ARRAYSIZE(recovered_message.data), plaintext, plaintext_len);
92  }
93  default:
94  // Unexpected number of words; should never get here.
95  return OTCRYPTO_FATAL_ERR;
96  }
97 
98  // Should be unreachable.
99  HARDENED_TRAP();
100  return OTCRYPTO_FATAL_ERR;
101 }
102 
103 status_t rsa_encrypt_3072_start(const rsa_3072_public_key_t *public_key,
104  const otcrypto_hash_mode_t hash_mode,
105  const uint8_t *message, size_t message_bytelen,
106  const uint8_t *label, size_t label_bytelen) {
107  // Encode the message.
108  rsa_3072_int_t encoded_message;
109  HARDENED_TRY(rsa_padding_oaep_encode(
110  hash_mode, message, message_bytelen, label, label_bytelen,
111  ARRAYSIZE(encoded_message.data), encoded_message.data));
112 
113  // Start computing (encoded_message ^ e) mod n with a variable-time
114  // exponentiation.
115  return rsa_modexp_vartime_3072_start(&encoded_message, public_key->e,
116  &public_key->n);
117 }
118 
119 status_t rsa_encrypt_3072_finalize(rsa_3072_int_t *ciphertext) {
120  return rsa_modexp_3072_finalize(ciphertext);
121 }
122 
123 status_t rsa_decrypt_3072_start(const rsa_3072_private_key_t *private_key,
124  const rsa_3072_int_t *ciphertext) {
125  // Start computing (ciphertext ^ d) mod n.
126  return rsa_modexp_consttime_3072_start(ciphertext, &private_key->d,
127  &private_key->n);
128 }
129 
130 status_t rsa_encrypt_4096_start(const rsa_4096_public_key_t *public_key,
131  const otcrypto_hash_mode_t hash_mode,
132  const uint8_t *message, size_t message_bytelen,
133  const uint8_t *label, size_t label_bytelen) {
134  // Encode the message.
135  rsa_4096_int_t encoded_message;
136  HARDENED_TRY(rsa_padding_oaep_encode(
137  hash_mode, message, message_bytelen, label, label_bytelen,
138  ARRAYSIZE(encoded_message.data), encoded_message.data));
139 
140  // Start computing (encoded_message ^ e) mod n with a variable-time
141  // exponentiation.
142  return rsa_modexp_vartime_4096_start(&encoded_message, public_key->e,
143  &public_key->n);
144 }
145 
146 status_t rsa_encrypt_4096_finalize(rsa_4096_int_t *ciphertext) {
147  return rsa_modexp_4096_finalize(ciphertext);
148 }
149 
150 status_t rsa_decrypt_4096_start(const rsa_4096_private_key_t *private_key,
151  const rsa_4096_int_t *ciphertext) {
152  // Start computing (ciphertext ^ d) mod n.
153  return rsa_modexp_consttime_4096_start(ciphertext, &private_key->d,
154  &private_key->n);
155 }