19static int check(RSA* key) {
21 int public_exponent, modulus;
22 RSA_get0_key(key, &n, &e, NULL);
23 public_exponent = BN_get_word(e);
24 modulus = BN_num_bits(n);
25 if (public_exponent != 3 && public_exponent != 65537) {
27 "WARNING: Public exponent should be 3 or 65537 (but is %d).\n",
30 if (modulus != 1024 && modulus != 2048 && modulus != 3072 && modulus != 4096
32 fprintf(stderr,
"ERROR: Unknown modulus length = %d.\n", modulus);
37static void native_to_big(
unsigned char* data,
size_t size) {
39 if (*(
unsigned char *)&tmp == 1) {
40 fprintf(stderr,
"WARNING: Assuming little endian encoding.\n");
41 for (i = 0; i <
size / 2; ++i) {
43 data[i] = data[
size - i - 1];
44 data[
size - i - 1] = tmp;
47 fprintf(stderr,
"WARNING: Assuming big endian encoding.\n");
51static void print_data(
void* context,
void* data,
size_t size) {
54 static size_t block = 0;
59 for (i = 0; i <
size; ++i, ++block) {
64 printf(
"%s0x%02x", block == 0 ?
"" :
", ", ((
uint8_t *)data)[i]);
68static void write_data(
void* context,
void* data,
size_t size) {
69 if (
size > 0 && fwrite(data,
size, 1, (FILE *)context) != 1) {
75static void output(RSA* key,
t_data_printer printer,
void *printer_ctx) {
79 BIGNUM *Big1 = NULL, *Big2 = NULL, *Big64 = NULL, *BigMinus1 = NULL;
81 BIGNUM *N0inv= NULL, *R = NULL, *RR = NULL, *RRTemp = NULL, *NnumBits = NULL;
82 BIGNUM *n = NULL, *rr = NULL;
83 BN_CTX *bn_ctx = BN_CTX_new();
86 nwords = RSA_size(key) / 8;
88 printer(printer_ctx, &nwords,
sizeof(nwords));
90 RSA_get0_key(key, &key_n, NULL, NULL);
103 BN_set_word(Big1, 1L);
104 BN_set_word(Big2, 2L);
105 BN_set_word(Big64, 64L);
106 BN_sub(BigMinus1, Big1, Big2);
108 BN_exp(B, Big2, Big64, bn_ctx);
110 BN_mod_inverse(N0inv,
N, B, bn_ctx);
111 BN_sub(N0inv, B, N0inv);
112 n0invout = (
uint64_t) BN_get_word(N0inv);
113 BN_rshift(N0inv, N0inv, 32);
114 n0invout |= (
uint64_t) BN_get_word(N0inv) << 32ULL;
115 printer(printer_ctx, &n0invout,
sizeof(n0invout));
117 BN_set_word(NnumBits, BN_num_bits(
N));
118 BN_exp(R, Big2, NnumBits, bn_ctx);
121 BN_mul(RRTemp, RR, R, bn_ctx);
122 BN_mod(RR, RRTemp,
N, bn_ctx);
124 for (i = 0; i < nwords*2; ++i) {
126 BN_mod(n,
N, B, bn_ctx);
127 nout = BN_get_word(n);
129 printer(printer_ctx, &nout,
sizeof(nout));
132 for (i = 0; i < nwords*2; ++i) {
134 BN_mod(rr, RR, B, bn_ctx);
135 rrout = BN_get_word(rr);
136 BN_rshift(RR, RR, 32);
137 printer(printer_ctx, &rrout,
sizeof(rrout));
140 printer(printer_ctx, NULL, 0);
157 if (fseek(fp, 0, SEEK_END))
return NULL;
158 if ((fsize = ftell(fp)) <= 0 || fsize > UINT_MAX)
return NULL;
159 if (fseek(fp, 0, SEEK_SET))
return NULL;
160 *
size = (
unsigned int)fsize;
161 if (!(data =
malloc(fsize)))
return NULL;
162 if (fread(data, fsize, 1, fp) == 1)
return data;
166int sign_file(FILE* fp,
const char* sigfile,
const char *pubkfile) {
169 EVP_PKEY* key = NULL;
170 const EVP_MD* md = NULL;
171 EVP_MD_CTX* ctx = NULL;
175 unsigned int fp_size = 0;
177 unsigned int signature_size;
180 if (!(fp_data =
read_file(fp, &fp_size)))
goto done;
181 if (!(rsa = RSA_new()))
goto done;
182 if (!(bn = BN_new()))
goto done;
183 if (!(md = EVP_sha256()))
goto done;
184 if (!(key = EVP_PKEY_new()))
goto done;
185 if (!(ctx = EVP_MD_CTX_create()))
goto done;
186 if (!BN_set_word(bn, RSA_F4))
goto done;
187 if (!RSA_generate_key_ex(rsa, 2048, bn, NULL))
goto done;
188 if (!EVP_PKEY_set1_RSA(key, rsa))
goto done;
189 if (EVP_PKEY_size(key) !=
sizeof(
signature))
goto done;
190 if (!EVP_SignInit(ctx, md))
goto done;
191 if (!EVP_SignUpdate(ctx, fp_data, fp_size))
goto done;
192 if (!EVP_SignFinal(ctx, &
signature[0], &signature_size, key))
goto done;
194 sigf = fopen(sigfile,
"wb");
195 if (!sigf)
goto done;
196 if (fwrite(
signature, signature_size, 1, sigf) != 1)
goto done;
197 pubkf = fopen(pubkfile,
"wb");
198 if (!pubkf)
goto done;
199 output(rsa, write_data, pubkf);
206 EVP_MD_CTX_cleanup(ctx);
208 if (sigf) fclose(sigf);
209 if (pubkf) fclose(pubkf);
220int main(
int argc,
char* argv[]) {
227 EVP_PKEY* key = NULL;
231 if (!strcmp(argv[1],
"-cert"))
233 else if (!strcmp(argv[1],
"-pub"))
235 else if (!strcmp(argv[1],
"-raw"))
237 }
else if (argc == 5) {
238 if (!strcmp(argv[1],
"-sign"))
242 progname = strrchr(argv[0],
'/');
247 fprintf(stderr,
"Usage: %s <-cert | -pub | -raw> <file>\n", progname);
248 fprintf(stderr,
"Usage: %s -sign <file> <signature> <pubkey>\n", progname);
251 fp = fopen(argv[2],
"r");
253 fprintf(stderr,
"Couldn't open file %s!\n", argv[2]);
258 int ret =
sign_file(fp, argv[3], argv[4]);
265 if (!PEM_read_X509(fp, &cert, NULL, NULL)) {
266 fprintf(stderr,
"Couldn't read certificate.\n");
270 key = X509_get_pubkey(cert);
272 if (!(pubkey = EVP_PKEY_get1_RSA(key))) {
273 fprintf(stderr,
"Couldn't convert to a RSA style key.\n");
278 if (!(pubkey = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL))) {
279 fprintf(stderr,
"Couldn't read public key file.\n");
284 static unsigned char expraw[4] = {0, 0, 0, 3};
285 static unsigned char modraw[1024];
286 if (fseek (fp, 0, SEEK_END) != 0
287 || (
size = ftell(fp)) < 0
288 || fseek(fp, 0, SEEK_SET) != 0) {
289 fprintf(stderr,
"Couldn't read modulus size.\n");
292 if ((
size_t)
size >
sizeof(modraw)) {
293 fprintf(stderr,
"Unsupported modulus size %ld.\n",
size);
296 if (fread(modraw,
size, 1, fp) != 1) {
297 fprintf(stderr,
"Couldn't read modulus number.\n");
300 native_to_big(modraw, (
size_t)
size);
301 if (!(mod = BN_bin2bn(modraw, (
int)
size, NULL))) {
302 fprintf(stderr,
"Couldn't create modulus number.\n");
305 if (!(exp = BN_bin2bn(expraw,
sizeof(expraw), NULL))) {
306 fprintf(stderr,
"Couldn't create public exp number.\n");
309 if (!(pubkey = RSA_new()) || !RSA_set0_key(pubkey, mod, exp, NULL)) {
310 fprintf(stderr,
"Couldn't create rsa public key.\n");
317 output(pubkey, print_data, NULL);