int tpm_rsa_import_key(tpm_rsa_private_key_t *key, int endian, const uint8_t *n, size_t n_len, const uint8_t *e, size_t e_len, const uint8_t *p, const uint8_t *q) { tpm_bn_t t1, t2, phi; if (n == NULL || n_len == 0 || (p == NULL && q == NULL)) return -1; /* init key */ key->size = n_len << 3; if (e == NULL || e_len == 0) { tpm_bn_init_set_ui(key->e, 65537); } else { tpm_bn_init2(key->e, e_len << 3); tpm_bn_import(key->e, e_len, endian, e); } tpm_bn_init2(key->n, key->size); tpm_bn_init2(key->p, key->size / 2); tpm_bn_init2(key->q, key->size / 2); tpm_bn_init2(key->d, key->size); tpm_bn_init2(key->u, key->size / 2); tpm_bn_init2(t1, key->size / 2); tpm_bn_init2(t2, key->size / 2); tpm_bn_init2(phi, key->size); /* import values */ tpm_bn_import(key->n, n_len, endian, n); if (p != NULL) tpm_bn_import(key->p, n_len / 2, endian, p); if (q != NULL) tpm_bn_import(key->q, n_len / 2, endian, q); if (p == NULL) tpm_bn_tdiv_q(key->p, key->n, key->q); if (q == NULL) tpm_bn_tdiv_q(key->q, key->n, key->p); /* p shall be smaller than q */ if (tpm_bn_cmp(key->p, key->q) > 0) tpm_bn_swap(key->p, key->q); /* calculate missing values */ tpm_bn_sub_ui(t1, key->p, 1); tpm_bn_sub_ui(t2, key->q, 1); tpm_bn_mul(phi, t1, t2); tpm_bn_invert(key->d, key->e, phi); tpm_bn_invert(key->u, key->p, key->q); /* release helper variables */ tpm_bn_clear(t1); tpm_bn_clear(t2); tpm_bn_clear(phi); /* test key */ if (rsa_test_key(key) != 0) { tpm_rsa_release_private_key(key); return -1; } return 0; }
int rsa_import_key(rsa_private_key_t *key, int endian, uint8_t *n, size_t n_len, uint8_t *e, size_t e_len, uint8_t *p, uint8_t *q) { mpz_t t1, t2, phi; if (n == NULL || n_len == 0 || (p == NULL && q == NULL)) return -1; /* init key */ key->size = n_len << 3; if (e == NULL || e_len == 0) { mpz_init_set_ui(key->e, 65537); } else { mpz_init2(key->e, (e_len << 3) + GMP_NUMB_BITS); mpz_import(key->e, e_len, endian, 1, 0, 0, e); } mpz_init2(key->n, key->size + GMP_NUMB_BITS); mpz_init2(key->p, key->size / 2 + GMP_NUMB_BITS); mpz_init2(key->q, key->size / 2 + GMP_NUMB_BITS); mpz_init2(key->d, key->size + GMP_NUMB_BITS); mpz_init2(key->u, key->size / 2 + GMP_NUMB_BITS); mpz_init2(t1, key->size / 2 + GMP_NUMB_BITS); mpz_init2(t2, key->size / 2 + GMP_NUMB_BITS); mpz_init2(phi, key->size + GMP_NUMB_BITS); /* import values */ mpz_import(key->n, n_len, endian, 1, 0, 0, n); if (p != NULL) mpz_import(key->p, n_len / 2, endian, 1, 0, 0, p); if (q != NULL) mpz_import(key->q, n_len / 2, endian, 1, 0, 0, q); if (p == NULL) mpz_tdiv_q(key->p, key->n, key->q); if (q == NULL) mpz_tdiv_q(key->q, key->n, key->p); /* p shall be smaller than q */ if (mpz_cmp(key->p, key->q) > 0) mpz_swap(key->p, key->q); /* calculate missing values */ mpz_sub_ui(t1, key->p, 1); mpz_sub_ui(t2, key->q, 1); mpz_mul(phi, t1, t2); mpz_invert(key->d, key->e, phi); mpz_invert(key->u, key->p, key->q); /* release helper variables */ mpz_clear(t1); mpz_clear(t2); mpz_clear(phi); /* test key */ if (rsa_test_key(key) != 0) { rsa_release_private_key(key); return -1; } return 0; }
int rsa_generate_key(rsa_private_key_t *key, int key_size) { mpz_t e, p, q, n, t1, t2, phi, d, u; /* bit_size must be even */ if (key_size & 0x01) key_size++; /* we use e = 65537 */ mpz_init_set_ui(e, 65537); mpz_init2(p, key_size / 2 + GMP_NUMB_BITS); mpz_init2(q, key_size / 2 + GMP_NUMB_BITS); mpz_init2(n, key_size + GMP_NUMB_BITS); mpz_init2(t1, key_size / 2 + GMP_NUMB_BITS); mpz_init2(t2, key_size / 2 + GMP_NUMB_BITS); mpz_init2(phi, key_size + GMP_NUMB_BITS); mpz_init2(d, key_size + GMP_NUMB_BITS); mpz_init2(u, key_size / 2 + GMP_NUMB_BITS); do { /* get prime p */ mpz_urandomb(p, NULL, key_size / 2); mpz_setbit(p, 0); mpz_setbit(p, key_size / 2 - 1); mpz_setbit(p, key_size / 2 - 2); mpz_nextprime(p, p); mpz_sub_ui(t1, p, 1); mpz_gcd(phi, e, t1); if (mpz_cmp_ui(phi, 1) != 0) continue; /* get prime q */ mpz_urandomb(q, NULL, key_size / 2); mpz_setbit(q, 0); mpz_setbit(q, key_size / 2 - 1); mpz_setbit(q, key_size / 2 - 2); mpz_nextprime(q, q); mpz_sub_ui(t2, q, 1); mpz_gcd(phi, e, t1); if (mpz_cmp_ui(phi, 1) != 0) continue; /* p shall be smaller than q */ if (mpz_cmp(p, q) > 0) mpz_swap(p, q); /* calculate the modulus */ mpz_mul(n, p, q); } while (mpz_sizeinbase(n, 2) != key_size); /* calculate Euler totient: phi = (p-1)(q-1) */ mpz_mul(phi, t1, t2); /* calculate the secret key d = e^(-1) mod phi */ mpz_invert(d, e, phi); /* calculate the inverse of p and q (used for chinese remainder theorem) */ mpz_invert(u, p, q); /* setup private key */ mpz_init_set(key->n, n); mpz_init_set(key->e, e); mpz_init_set(key->p, p); mpz_init_set(key->q, q); mpz_init_set(key->d, d); mpz_init_set(key->u, u); key->size = key_size; /* release helper variables */ mpz_clear(e); mpz_clear(p); mpz_clear(q); mpz_clear(n); mpz_clear(t1); mpz_clear(t2); mpz_clear(phi); mpz_clear(d); mpz_clear(u); /* test key */ if (rsa_test_key(key) != 0) { rsa_release_private_key(key); return -1; } return 0; }