4
* RSA key generator for the suspend and resume tools.
6
* Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
8
* This file is released under the GPLv2.
12
#include <sys/types.h>
25
#define MIN_KEY_BITS 1024
26
#define MAX_KEY_BITS 4096
27
#define MAX_OUT_SIZE (sizeof(struct RSA_data))
28
#define MAX_STR_LEN 256
29
#define DEFAULT_FILE "suspend.key"
31
static char in_buffer[MAX_STR_LEN];
32
static char pass_buf[MAX_STR_LEN];
33
static struct RSA_data rsa;
34
static unsigned char encrypt_buffer[RSA_DATA_SIZE];
36
int main(int argc, char *argv[])
38
gcry_ac_data_t rsa_data_set;
39
gcry_ac_handle_t rsa_hd;
40
gcry_ac_key_t rsa_priv;
41
gcry_ac_key_pair_t rsa_key_pair;
44
int len = MIN_KEY_BITS, ret = EXIT_SUCCESS;
45
struct termios termios;
48
unsigned char key_buf[PK_KEY_SIZE];
49
gcry_cipher_hd_t sym_hd;
50
unsigned char ivec[PK_CIPHER_BLOCK];
54
printf("libgcrypt version: %s\n", gcry_check_version(NULL));
55
gcry_control(GCRYCTL_INIT_SECMEM, 4096, 0);
56
ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
61
printf("Key bits (between %d and %d inclusive) [%d]: ",
62
MIN_KEY_BITS, MAX_KEY_BITS, len);
63
fgets(in_buffer, MAX_STR_LEN, stdin);
64
if (strlen(in_buffer) && *in_buffer != '\n')
65
sscanf(in_buffer, "%d", &len);
66
} while (len < MIN_KEY_BITS || len > MAX_KEY_BITS);
69
printf("Generating %d-bit RSA keys. Please wait.\n", len);
70
ret = gcry_ac_key_pair_generate(rsa_hd, len, NULL, &rsa_key_pair, NULL);
72
fprintf(stderr, "Key generation failed: %s\n", gcry_strerror(ret));
76
printf("Testing the private key. Please wait.\n");
77
rsa_priv = gcry_ac_key_pair_extract(rsa_key_pair, GCRY_AC_KEY_SECRET);
78
ret = gcry_ac_key_test(rsa_hd, rsa_priv);
80
printf("RSA key test failed. Retrying.\n");
84
rsa_data_set = gcry_ac_key_data_get(rsa_priv);
85
if (gcry_ac_data_length(rsa_data_set) != RSA_FIELDS) {
86
fprintf(stderr, "Wrong number of key fields\n");
91
/* Convert the key length into bytes */
92
size = (len + 7) >> 3;
93
/* Copy the public key components to struct RSA_data */
95
for (j = 0; j < RSA_FIELDS_PUB; j++) {
99
if (offset + size >= RSA_DATA_SIZE)
102
gcry_ac_data_get_index(rsa_data_set, GCRY_AC_FLAG_COPY, j,
103
(const char **)&str, &mpi);
104
gcry_mpi_print(GCRYMPI_FMT_USG, rsa.data + offset,
106
rsa.field[j][0] = str[0];
107
rsa.field[j][1] = '\0';
110
gcry_mpi_release(mpi);
114
tcgetattr(0, &termios);
115
termios.c_lflag &= ~ECHO;
116
termios.c_lflag |= ICANON | ECHONL;
117
tcsetattr(0, TCSANOW, &termios);
118
vrfy_buf = (char *)encrypt_buffer;
121
printf("Passphrase please (must be non-empty): ");
122
fgets(pass_buf, MAX_STR_LEN, stdin);
123
len = strlen(pass_buf) - 1;
125
if (pass_buf[len] == '\n')
126
pass_buf[len] = '\0';
127
printf("Confirm passphrase: ");
128
fgets(vrfy_buf, MAX_STR_LEN, stdin);
129
if (vrfy_buf[len] == '\n')
130
vrfy_buf[len] = '\0';
131
} while (strncmp(pass_buf, vrfy_buf, MAX_STR_LEN));
132
termios.c_lflag |= ECHO;
133
tcsetattr(0, TCSANOW, &termios);
135
memset(ivec, 0, PK_CIPHER_BLOCK);
136
strncpy((char *)ivec, pass_buf, PK_CIPHER_BLOCK);
138
md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
139
md5_finish_ctx(&ctx, key_buf);
141
/* First, we encrypt the key test */
142
ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
147
ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
149
ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK);
152
ret = gcry_cipher_encrypt(sym_hd, rsa.key_test, KEY_TEST_SIZE,
153
KEY_TEST_DATA, KEY_TEST_SIZE);
155
gcry_cipher_close(sym_hd);
159
/* Now, we can encrypt the private RSA key */
160
ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
165
ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
167
ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK);
172
/* Copy the private key components (encrypted) to struct RSA_data */
173
for (j = RSA_FIELDS_PUB; j < RSA_FIELDS; j++) {
177
if (offset + size >= RSA_DATA_SIZE)
180
gcry_ac_data_get_index(rsa_data_set, GCRY_AC_FLAG_COPY, j,
181
(const char **)&str, &mpi);
182
gcry_mpi_print(GCRYMPI_FMT_USG, rsa.data + offset,
185
/* We encrypt the data in place */
186
ret = gcry_cipher_encrypt(sym_hd, rsa.data + offset, s, NULL, 0);
190
rsa.field[j][0] = str[0];
191
rsa.field[j][1] = '\0';
194
gcry_mpi_release(mpi);
198
size = offset + sizeof(struct RSA_data) - RSA_DATA_SIZE;
200
printf("File name [%s]: ", DEFAULT_FILE);
201
fgets(in_buffer, MAX_STR_LEN, stdin);
202
if (!strlen(in_buffer) || *in_buffer == '\n')
203
strcpy(in_buffer, DEFAULT_FILE);
204
else if (in_buffer[strlen(in_buffer)-1] == '\n')
205
in_buffer[strlen(in_buffer)-1] = '\0';
206
fd = open(in_buffer, O_RDWR | O_CREAT | O_TRUNC, 00600);
208
write(fd, &rsa, size);
211
fprintf(stderr, "Could not open the file %s\n", in_buffer);
215
gcry_cipher_close(sym_hd);
217
gcry_ac_data_destroy(rsa_data_set);
219
gcry_ac_close(rsa_hd);