~ubuntu-branches/debian/stretch/uswsusp/stretch

« back to all changes in this revision

Viewing changes to keygen.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-08-11 09:42:59 UTC
  • Revision ID: james.westby@ubuntu.com-20060811094259-xbpx53fo39c0xl8y
Tags: 0.1
Initial Release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * keygen.c
 
3
 *
 
4
 * RSA key generator for the suspend and resume tools.
 
5
 *
 
6
 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
 
7
 *
 
8
 * This file is released under the GPLv2.
 
9
 *
 
10
 */
 
11
 
 
12
#include <sys/types.h>
 
13
#include <sys/stat.h>
 
14
#include <fcntl.h>
 
15
#include <unistd.h>
 
16
#include <errno.h>
 
17
#include <stdlib.h>
 
18
#include <stdio.h>
 
19
#include <string.h>
 
20
#include <termios.h>
 
21
 
 
22
#include "md5.h"
 
23
#include "encrypt.h"
 
24
 
 
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"
 
30
 
 
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];
 
35
 
 
36
int main(int argc, char *argv[])
 
37
{
 
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;
 
42
        gcry_mpi_t mpi;
 
43
        size_t offset;
 
44
        int len = MIN_KEY_BITS, ret = EXIT_SUCCESS;
 
45
        struct termios termios;
 
46
        char *vrfy_buf;
 
47
        struct md5_ctx ctx;
 
48
        unsigned char key_buf[PK_KEY_SIZE];
 
49
        gcry_cipher_hd_t sym_hd;
 
50
        unsigned char ivec[PK_CIPHER_BLOCK];
 
51
        unsigned short size;
 
52
        int j, fd;
 
53
 
 
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);
 
57
        if (ret)
 
58
                return ret;
 
59
 
 
60
        do {
 
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);
 
67
 
 
68
Retry:
 
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);
 
71
        if (ret) {
 
72
                fprintf(stderr, "Key generation failed: %s\n", gcry_strerror(ret));
 
73
                ret = EXIT_FAILURE;
 
74
                goto Close_RSA;
 
75
        }
 
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);
 
79
        if (ret) {
 
80
                printf("RSA key test failed.  Retrying.\n");
 
81
                goto Retry;
 
82
        }
 
83
 
 
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");
 
87
                ret = -EINVAL;
 
88
                goto Free_RSA;
 
89
        }
 
90
 
 
91
        /* Convert the key length into bytes */
 
92
        size = (len + 7) >> 3;
 
93
        /* Copy the public key components to struct RSA_data */
 
94
        offset = 0;
 
95
        for (j = 0; j < RSA_FIELDS_PUB; j++) {
 
96
                char *str;
 
97
                size_t s;
 
98
 
 
99
                if (offset + size >= RSA_DATA_SIZE)
 
100
                        goto Free_RSA;
 
101
 
 
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,
 
105
                                        size, &s, mpi);
 
106
                rsa.field[j][0] = str[0];
 
107
                rsa.field[j][1] = '\0';
 
108
                rsa.size[j] = s;
 
109
                offset += s;
 
110
                gcry_mpi_release(mpi);
 
111
                gcry_free(str);
 
112
        }
 
113
 
 
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;
 
119
        do {
 
120
                do {
 
121
                        printf("Passphrase please (must be non-empty): ");
 
122
                        fgets(pass_buf, MAX_STR_LEN, stdin);
 
123
                        len = strlen(pass_buf) - 1;
 
124
                } while (len <= 0);
 
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);
 
134
 
 
135
        memset(ivec, 0, PK_CIPHER_BLOCK);
 
136
        strncpy((char *)ivec, pass_buf, PK_CIPHER_BLOCK);
 
137
        md5_init_ctx(&ctx);
 
138
        md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
 
139
        md5_finish_ctx(&ctx, key_buf);
 
140
 
 
141
        /* First, we encrypt the key test */
 
142
        ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
 
143
                                GCRY_CIPHER_SECURE);
 
144
        if (ret)
 
145
                goto Free_RSA;
 
146
 
 
147
        ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
 
148
        if (!ret)
 
149
                ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK);
 
150
 
 
151
        if (!ret)
 
152
                ret = gcry_cipher_encrypt(sym_hd, rsa.key_test, KEY_TEST_SIZE,
 
153
                                        KEY_TEST_DATA, KEY_TEST_SIZE);
 
154
 
 
155
        gcry_cipher_close(sym_hd);
 
156
        if (ret)
 
157
                goto Free_RSA;
 
158
 
 
159
        /* Now, we can encrypt the private RSA key */
 
160
        ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
 
161
                                GCRY_CIPHER_SECURE);
 
162
        if (ret)
 
163
                goto Free_RSA;
 
164
 
 
165
        ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
 
166
        if (!ret)
 
167
                ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK);
 
168
 
 
169
        if (ret)
 
170
                goto Free_sym;
 
171
 
 
172
        /* Copy the private key components (encrypted) to struct RSA_data */
 
173
        for (j = RSA_FIELDS_PUB; j < RSA_FIELDS; j++) {
 
174
                char *str;
 
175
                size_t s;
 
176
 
 
177
                if (offset + size >= RSA_DATA_SIZE)
 
178
                        goto Free_sym;
 
179
 
 
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,
 
183
                                        size, &s, mpi);
 
184
 
 
185
                /* We encrypt the data in place */
 
186
                ret = gcry_cipher_encrypt(sym_hd, rsa.data + offset, s, NULL, 0);
 
187
                if (ret)
 
188
                        goto Free_sym;
 
189
 
 
190
                rsa.field[j][0] = str[0];
 
191
                rsa.field[j][1] = '\0';
 
192
                rsa.size[j] = s;
 
193
                offset += s;
 
194
                gcry_mpi_release(mpi);
 
195
                gcry_free(str);
 
196
        }
 
197
 
 
198
        size = offset + sizeof(struct RSA_data) - RSA_DATA_SIZE;
 
199
 
 
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);
 
207
        if (fd >= 0) {
 
208
                write(fd, &rsa, size);
 
209
                close(fd);
 
210
        } else {
 
211
                fprintf(stderr, "Could not open the file %s\n", in_buffer);
 
212
                ret = EXIT_FAILURE;
 
213
        }
 
214
Free_sym:
 
215
        gcry_cipher_close(sym_hd);
 
216
Free_RSA:
 
217
        gcry_ac_data_destroy(rsa_data_set);
 
218
Close_RSA:
 
219
        gcry_ac_close(rsa_hd);
 
220
 
 
221
        return ret;
 
222
}