aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cryptech.h10
-rw-r--r--rsa.c105
2 files changed, 82 insertions, 33 deletions
diff --git a/cryptech.h b/cryptech.h
index d8f1208..b0a7c35 100644
--- a/cryptech.h
+++ b/cryptech.h
@@ -628,6 +628,16 @@ extern hal_error_t hal_rsa_key_load(const hal_rsa_key_type_t type,
const uint8_t * const dP, const size_t dP_len,
const uint8_t * const dQ, const size_t dQ_len);
+extern hal_error_t hal_rsa_key_get_modulus(hal_rsa_key_t key,
+ uint8_t *modulus,
+ size_t *modulus_len,
+ const size_t modulus_max);
+
+extern hal_error_t hal_rsa_key_get_public_exponent(hal_rsa_key_t key,
+ uint8_t *public_exponent,
+ size_t *public_exponent_len,
+ const size_t public_exponent_max);
+
extern void hal_rsa_key_clear(hal_rsa_key_t key);
extern hal_error_t hal_rsa_encrypt(hal_rsa_key_t key,
diff --git a/rsa.c b/rsa.c
index 85ac8ee..ef334b6 100644
--- a/rsa.c
+++ b/rsa.c
@@ -43,6 +43,7 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
+#include <stddef.h>
#include <string.h>
#include <assert.h>
@@ -99,7 +100,7 @@ void hal_rsa_set_blinding(const int onoff)
* RSA key implementation. This structure type is private to this
* module, anything else that needs to touch one of these just gets a
* typed opaque pointer. We do, however, export the size, so that we
- * can make memory allocation the caller's problem (well, maybe).
+ * can make memory allocation the caller's problem.
*/
struct rsa_key {
@@ -117,14 +118,7 @@ struct rsa_key {
const size_t hal_rsa_key_t_size = sizeof(struct rsa_key);
/*
- * In the long run we want a full RSA implementation, or enough of one
- * to cover what we need in PKCS #11. For the moment, though, the
- * most urgent thing is to see whether this approach to performing the
- * CRT calculation works (and is any faster), followed by whether we
- * can use this approach for key generation.
- *
- * So don't worry about whether the following functions are what we
- * want in the long run, they'll probably evolve as we go.
+ * Error handling.
*/
#define lose(_code_) \
@@ -166,7 +160,7 @@ static hal_error_t unpack_fp(fp_int *bn, uint8_t *buffer, const size_t length)
#if HAL_RSA_USE_MODEXP
/*
- * Unwrap bignums into byte arrays, feeds them into hal_modexp(), and
+ * Unwrap bignums into byte arrays, feed them into hal_modexp(), and
* wrap result back up as a bignum.
*/
@@ -204,7 +198,7 @@ static hal_error_t modexp(fp_int *msg, fp_int *exp, fp_int *mod, fp_int *res)
/*
* Wrapper to let us export our modexp function as a replacement for
- * TFM's, to avoid dragging all of the TFM montgomery code in when we
+ * TFM's, to avoid dragging in all of the TFM montgomery code when we
* use TFM's Miller-Rabin test code.
*
* This code is here rather than in a separate module because of the
@@ -335,6 +329,9 @@ static hal_error_t rsa_crt(struct rsa_key *key, fp_int *msg, fp_int *sig)
/*
* Public API for raw RSA encryption and decryption.
+ *
+ * NB: This does not handle PKCS #1.5 padding, at the moment that's up
+ * to the caller.
*/
hal_error_t hal_rsa_encrypt(hal_rsa_key_t key_,
@@ -456,6 +453,51 @@ hal_error_t hal_rsa_key_load(const hal_rsa_key_type_t type,
return HAL_ERROR_BAD_ARGUMENTS;
}
+/*
+ * Extract public key components.
+ */
+
+static hal_error_t extract_component(hal_rsa_key_t key_, const size_t offset,
+ uint8_t *res, size_t *res_len, const size_t res_max)
+{
+ if (key_.key == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ fp_int *bn = (fp_int *) (((uint8_t *) key_.key) + offset);
+
+ const size_t len = fp_unsigned_bin_size(bn);
+
+ if (res_len != NULL)
+ *res_len = len;
+
+ if (len > res_max)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ memset(res, 0, res_max);
+ fp_to_unsigned_bin(bn, res);
+ return HAL_OK;
+}
+
+hal_error_t hal_rsa_key_get_modulus(hal_rsa_key_t key_,
+ uint8_t *res, size_t *res_len, const size_t res_max)
+{
+ return extract_component(key_, offsetof(struct rsa_key, n), res, res_len, res_max);
+}
+
+hal_error_t hal_rsa_key_get_public_exponent(hal_rsa_key_t key_,
+ uint8_t *res, size_t *res_len, const size_t res_max)
+{
+ return extract_component(key_, offsetof(struct rsa_key, e), res, res_len, res_max);
+}
+
+/*
+ * Generate a prime factor for an RSA keypair.
+ *
+ * Get random bytes, munge a few bits, and stuff into a bignum. Keep
+ * doing this until we find a result that's (probably) prime and for
+ * which result - 1 is relatively prime with respect to e.
+ */
+
static hal_error_t find_prime(unsigned prime_length, fp_int *e, fp_int *result)
{
uint8_t buffer[prime_length];
@@ -464,12 +506,6 @@ static hal_error_t find_prime(unsigned prime_length, fp_int *e, fp_int *result)
fp_init(&t);
- /*
- * Get random bytes, munge a few bits, and stuff into a bignum.
- * Keep doing this until we find a result that's (probably) prime
- * and for which result - 1 is relatively prime with respect to e.
- */
-
do {
if ((err = hal_get_random(buffer, sizeof(buffer))) != HAL_OK)
return err;
@@ -484,6 +520,10 @@ static hal_error_t find_prime(unsigned prime_length, fp_int *e, fp_int *result)
return HAL_OK;
}
+/*
+ * Generate a new RSA keypair.
+ */
+
hal_error_t hal_rsa_key_gen(hal_rsa_key_t *key_,
void *keybuf, const size_t keybuf_len,
const unsigned key_length,
@@ -553,6 +593,21 @@ hal_error_t hal_rsa_key_gen(hal_rsa_key_t *key_,
#define ASN1_INTEGER 0x02
#define ASN1_SEQUENCE 0x30
+/*
+ * RSAPrivateKey fields in the required order.
+ */
+
+#define RSAPrivateKey_fields \
+ _(&version); \
+ _(&key->n); \
+ _(&key->e); \
+ _(&key->d); \
+ _(&key->p); \
+ _(&key->q); \
+ _(&key->dP); \
+ _(&key->dQ); \
+ _(&key->u);
+
static size_t count_length(size_t length)
{
size_t result = 1;
@@ -682,22 +737,6 @@ static hal_error_t decode_integer(fp_int *bn,
return HAL_OK;
}
-/*
- * RSAPrivateKey fields in the required order.
- */
-
-#define RSAPrivateKey_fields \
- _(&version); \
- _(&key->n); \
- _(&key->e); \
- _(&key->d); \
- _(&key->p); \
- _(&key->q); \
- _(&key->dP); \
- _(&key->dQ); \
- _(&key->u);
-
-
hal_error_t hal_rsa_key_to_der(hal_rsa_key_t key_,
uint8_t *der, size_t *der_len, const size_t der_max)
{