Skip to content

Commit

Permalink
[crypto] Change the way RSA encryption returns plaintext len.
Browse files Browse the repository at this point in the history
Now that the output buffer is passed by value, the length must be
returned separately.

Signed-off-by: Jade Philipoom <[email protected]>
  • Loading branch information
jadephilipoom committed Jan 25, 2024
1 parent 277faab commit dc7402f
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 31 deletions.
23 changes: 11 additions & 12 deletions sw/device/lib/crypto/impl/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,10 @@ otcrypto_status_t otcrypto_rsa_decrypt(
const otcrypto_blinded_key_t *private_key,
const otcrypto_hash_mode_t hash_mode,
otcrypto_const_word32_buf_t ciphertext, otcrypto_const_byte_buf_t label,
otcrypto_byte_buf_t plaintext) {
otcrypto_byte_buf_t plaintext, size_t *plaintext_bytelen) {
HARDENED_TRY(otcrypto_rsa_decrypt_async_start(private_key, ciphertext));
return otcrypto_rsa_decrypt_async_finalize(hash_mode, label, plaintext);
return otcrypto_rsa_decrypt_async_finalize(hash_mode, label, plaintext,
plaintext_bytelen);
}

/**
Expand Down Expand Up @@ -851,15 +852,15 @@ otcrypto_status_t otcrypto_rsa_encrypt_async_finalize(
return rsa_encrypt_2048_finalize(ctext);
}
case kRsa3072NumWords: {
HARDENED_CHECK_EQ(ciphertext->len * sizeof(uint32_t),
HARDENED_CHECK_EQ(ciphertext.len * sizeof(uint32_t),
sizeof(rsa_3072_int_t));
rsa_3072_int_t *ctext = (rsa_3072_int_t *)ciphertext->data;
rsa_3072_int_t *ctext = (rsa_3072_int_t *)ciphertext.data;
return rsa_encrypt_3072_finalize(ctext);
}
case kRsa4096NumWords: {
HARDENED_CHECK_EQ(ciphertext->len * sizeof(uint32_t),
HARDENED_CHECK_EQ(ciphertext.len * sizeof(uint32_t),
sizeof(rsa_4096_int_t));
rsa_4096_int_t *ctext = (rsa_4096_int_t *)ciphertext->data;
rsa_4096_int_t *ctext = (rsa_4096_int_t *)ciphertext.data;
return rsa_encrypt_4096_finalize(ctext);
}
default:
Expand Down Expand Up @@ -951,25 +952,23 @@ otcrypto_status_t otcrypto_rsa_decrypt_async_start(

otcrypto_status_t otcrypto_rsa_decrypt_async_finalize(
const otcrypto_hash_mode_t hash_mode, otcrypto_const_byte_buf_t label,
otcrypto_byte_buf_t plaintext) {
otcrypto_byte_buf_t plaintext, size_t *plaintext_bytelen) {
if (plaintext.data == NULL || label.data == NULL) {
return OTCRYPTO_BAD_ARGS;
}

// Call the unified `finalize()` operation, which will infer the RSA size
// from OTBN.
size_t actual_plaintext_len;
HARDENED_TRY(rsa_decrypt_finalize(hash_mode, label.data, label.len,
plaintext.len, plaintext.data,
&actual_plaintext_len));
plaintext_bytelen));

// Consistency check; this should never happen.
if (launder32(actual_plaintext_len) >= plaintext.len) {
if (launder32(*plaintext_bytelen) >= plaintext.len) {
HARDENED_TRAP();
return OTCRYPTO_FATAL_ERR;
}
HARDENED_CHECK_LE(actual_plaintext_len, plaintext.len);
HARDENED_CHECK_LE(*plaintext_bytelen, plaintext.len);

plaintext.len = actual_plaintext_len;
return OTCRYPTO_OK;
}
11 changes: 6 additions & 5 deletions sw/device/lib/crypto/include/rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,8 @@ otcrypto_status_t otcrypto_rsa_encrypt(
* of the hash function digest. If the plaintext buffer is not long enough,
* this function will return an error.
*
* If the plaintext buffer is longer than necessary, this function will change
* the `len` field in `plaintext` to match the actual plaintext length. At this
* point, excess memory at the end of the buffer may be safely freed.
* Decryption recovers the original length of the plaintext buffer and will
* return its value in `plaintext_bytelen`.
*
* Note: RSA encryption is included for compatibility with legacy interfaces,
* and is typically not recommended for modern applications because it is
Expand All @@ -263,13 +262,14 @@ otcrypto_status_t otcrypto_rsa_encrypt(
* @param ciphertext Ciphertext to decrypt.
* @param label Label for OAEP encoding.
* @param[out] plaintext Buffer for the decrypted message.
* @param[out] plaintext_bytelen Recovered byte-length of plaintext.
* @return Result of the RSA decryption operation.
*/
otcrypto_status_t otcrypto_rsa_decrypt(
const otcrypto_blinded_key_t *private_key,
const otcrypto_hash_mode_t hash_mode,
otcrypto_const_word32_buf_t ciphertext, otcrypto_const_byte_buf_t label,
otcrypto_byte_buf_t plaintext);
otcrypto_byte_buf_t plaintext, size_t *plaintext_bytelen);
/**
* Starts the asynchronous RSA key generation function.
*
Expand Down Expand Up @@ -442,11 +442,12 @@ otcrypto_status_t otcrypto_rsa_decrypt_async_start(
* @param hash_mode Hash function to use for OAEP encoding.
* @param label Label for OAEP encoding.
* @param[out] plaintext Buffer for the decrypted message.
* @param[out] plaintext_bytelen Recovered byte-length of plaintext.
* @return Result of the RSA decryption finalize operation.
*/
otcrypto_status_t otcrypto_rsa_decrypt_async_finalize(
const otcrypto_hash_mode_t hash_mode, otcrypto_const_byte_buf_t label,
otcrypto_byte_buf_t plaintext);
otcrypto_byte_buf_t plaintext, size_t *plaintext_bytelen);

#ifdef __cplusplus
} // extern "C"
Expand Down
5 changes: 1 addition & 4 deletions sw/device/tests/crypto/rsa_2048_encryption_functest.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,9 @@ static status_t run_rsa_2048_decrypt(const uint8_t *label, size_t label_len,
};
uint64_t t_start = profile_start();
TRY(otcrypto_rsa_decrypt(&private_key, kTestHashMode, ciphertext_buf,
label_buf, plaintext_buf));
label_buf, plaintext_buf, msg_len));
profile_end_and_print(t_start, "RSA-2048 decryption");

// Write the actual plaintext length to `msg_len`.
*msg_len = plaintext_buf.len;

return OK_STATUS();
}

Expand Down
7 changes: 2 additions & 5 deletions sw/device/tests/crypto/rsa_3072_encryption_functest.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static status_t run_rsa_3072_encrypt(const uint8_t *msg, size_t msg_len,
};
uint64_t t_start = profile_start();
TRY(otcrypto_rsa_encrypt(&public_key, kTestHashMode, msg_buf, label_buf,
&ciphertext_buf));
ciphertext_buf));
profile_end_and_print(t_start, "RSA-3072 encryption");

return OK_STATUS();
Expand Down Expand Up @@ -214,12 +214,9 @@ static status_t run_rsa_3072_decrypt(const uint8_t *label, size_t label_len,
};
uint64_t t_start = profile_start();
TRY(otcrypto_rsa_decrypt(&private_key, kTestHashMode, ciphertext_buf,
label_buf, &plaintext_buf));
label_buf, plaintext_buf, msg_len));
profile_end_and_print(t_start, "RSA-3072 decryption");

// Write the actual plaintext length to `msg_len`.
*msg_len = plaintext_buf.len;

return OK_STATUS();
}

Expand Down
7 changes: 2 additions & 5 deletions sw/device/tests/crypto/rsa_4096_encryption_functest.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static status_t run_rsa_4096_encrypt(const uint8_t *msg, size_t msg_len,
};
uint64_t t_start = profile_start();
TRY(otcrypto_rsa_encrypt(&public_key, kTestHashMode, msg_buf, label_buf,
&ciphertext_buf));
ciphertext_buf));
profile_end_and_print(t_start, "RSA-4096 encryption");

return OK_STATUS();
Expand Down Expand Up @@ -234,12 +234,9 @@ static status_t run_rsa_4096_decrypt(const uint8_t *label, size_t label_len,
};
uint64_t t_start = profile_start();
TRY(otcrypto_rsa_decrypt(&private_key, kTestHashMode, ciphertext_buf,
label_buf, &plaintext_buf));
label_buf, plaintext_buf, msg_len));
profile_end_and_print(t_start, "RSA-4096 decryption");

// Write the actual plaintext length to `msg_len`.
*msg_len = plaintext_buf.len;

return OK_STATUS();
}

Expand Down

0 comments on commit dc7402f

Please sign in to comment.