Systemsicherheit/Assignment 7 - SGX Hands-on/rsa/rsa.c

201 lines
4.8 KiB
C
Raw Normal View History

2024-06-29 16:10:15 +02:00
#include "rsa.h"
#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int random_prime(mpz_t prime, const size_t size) {
u8 tmp[size];
FILE *urandom = fopen("/dev/urandom", "rb");
if((urandom == NULL) || (prime == NULL))
return 0;
fread(tmp, 1, size, urandom);
mpz_import(prime, size, 1, 1, 1, 0, tmp);
mpz_nextprime(prime, prime);
fclose(urandom);
return 1;
}
static int rsa_keygen(rsa_key *key) {
// null pointer handling
2024-06-29 16:10:15 +02:00
if(key == NULL)
return 0;
// init bignums
mpz_init_set_ui(key->e, 65537);
mpz_inits(key->p, key->q, key->n, key->d, NULL);
// prime gen
if ((!random_prime(key->p, MODULUS_SIZE/2)) || (!random_prime(key->q, MODULUS_SIZE/2)))
return 0;
// compute n
mpz_mul(key->n, key->p, key->q);
// compute phi(n)
mpz_t phi_n; mpz_init(phi_n);
mpz_sub_ui(key->p, key->p, 1);
mpz_sub_ui(key->q, key->q, 1);
mpz_mul(phi_n, key->p, key->q);
mpz_add_ui(key->p, key->p, 1);
mpz_add_ui(key->q, key->q, 1);
// compute d
if(mpz_invert(key->d, key->e, phi_n) == 0) {
return 0;
}
// free temporary phi_n and return true
mpz_clear(phi_n);
return 1;
}
static int rsa_export(rsa_key *key) {
}
static int rsa_import(rsa_key *key) {
return 0;
}
2024-06-29 16:10:15 +02:00
int rsa_init(rsa_key *key) {
if(rsa_import(key)) {
return 1;
2024-06-29 16:10:15 +02:00
} else {
return rsa_keygen(key);
2024-06-29 16:10:15 +02:00
}
return 0;
}
int rsa_public_init(rsa_public_key *key) {
// null pointer handling
if(key == NULL)
return 0;
mpz_init_set_ui(key->e, 65537);
mpz_init_set_str(key->n, "", 0);
2024-06-29 16:10:15 +02:00
}
void rsa_free(rsa_key *key) {
// free bignums
mpz_clears(key->p, key->q, key->n, key->e, key->d, NULL);
}
void rsa_public_free(rsa_public_key *key) {
// free bignums
mpz_clears(key->e, key->n, NULL);
}
2024-06-29 16:10:15 +02:00
static int pkcs1(mpz_t message, const u8 *data, const size_t length) {
// temporary buffer
u8 padded_bytes[MODULUS_SIZE];
// calculate padding size (how many 0xff bytes)
size_t padding_length = MODULUS_SIZE - length - 3;
2024-06-29 16:46:07 +02:00
if ((padding_length < 8) || (message == NULL) || (data == NULL)) {
2024-06-29 16:10:15 +02:00
// message to big
// or null pointer
return 0;
}
// set padding bytes
padded_bytes[0] = 0x00;
padded_bytes[1] = 0x01;
padded_bytes[2 + padding_length] = 0x00;
for (size_t i = 2; i < padding_length + 2; i++) {
padded_bytes[i] = 0xff;
}
// copy message bytes
memcpy(padded_bytes + padding_length + 3, data, length);
// convert padded message to mpz_t
mpz_import(message, MODULUS_SIZE, 1, 1, 0, 0, padded_bytes);
return 1;
}
size_t rsa_sign(u8 *sig, const u8 *sha256, const rsa_key *key) {
2024-06-29 16:10:15 +02:00
// null pointer handling
if((sig == NULL) || (sha256 == NULL) || (key == NULL))
return 0;
// init bignum message
mpz_t message; mpz_init(message);
mpz_t blinder; mpz_init(blinder);
// get random blinder
random_prime(blinder, MODULUS_SIZE - 10);
2024-06-29 16:10:15 +02:00
// add padding
if(!pkcs1(message, sha256, 32)) {
return 0;
}
// blind
mpz_mul(message, message, blinder);
mpz_mod(message, message, key->n);
mpz_invert(blinder, blinder, key->n);
mpz_powm(blinder, blinder, key->d, key->n);
2024-06-29 16:10:15 +02:00
// compute signature
mpz_powm(message, message, key->d, key->n);
// unblind
mpz_mul(message, message, blinder);
mpz_mod(message, message, key->n);
2024-06-29 16:10:15 +02:00
// export signature
size_t size = (mpz_sizeinbase(message, 2) + 7) / 8;
mpz_export(sig, &size, 1, 1, 0, 0, message);
// free bignum and return true
mpz_clears(message, blinder, NULL);
return size;
2024-06-29 16:10:15 +02:00
}
int rsa_verify(const u8 *sig, const size_t sig_length, const u8 *sha256, const rsa_public_key *pk) {
2024-06-29 16:10:15 +02:00
// null pointer handling
if((sig == NULL) || (sha256 == NULL) || (pk == NULL))
return 0;
2024-06-29 16:46:07 +02:00
// initialize bignums
mpz_t signature, message;
mpz_inits(signature, message, NULL);
2024-06-29 16:46:07 +02:00
// import signature
mpz_import(signature, (sig_length < MODULUS_SIZE) ? sig_length : MODULUS_SIZE, 1, 1, 0, 0, sig);
// revert rsa signing process
mpz_powm(signature, signature, pk->e, pk->n);
// rebuild signed message
if(!pkcs1(message, sha256, 32))
return 0;
2024-06-29 16:46:07 +02:00
// compare signature with expected value
if(mpz_cmp(signature, message) != 0)
return 0;
2024-06-29 16:10:15 +02:00
2024-06-29 16:46:07 +02:00
// free bignums and return valid signature
mpz_clears(signature, message, NULL);
2024-06-29 16:10:15 +02:00
return 1;
}
void rsa_print(const rsa_key *key) {
gmp_printf("%Zx\n", key->p);
gmp_printf("%Zx\n", key->q);
gmp_printf("%Zx\n", key->n);
gmp_printf("%Zx\n", key->e);
gmp_printf("%Zx\n", key->d);
}
void rsa_public_print(const rsa_public_key *pk) {
gmp_printf("%Zx\n", pk->e);
gmp_printf("%Zx\n", pk->n);
2024-06-29 16:46:07 +02:00
}