Revert "Merge branch 'upstream' into tizen"
[platform/upstream/nettle.git] / examples / rsa-encrypt.c
1 /* rsa-encrypt.c
2  *
3  */
4
5 /* nettle, low-level cryptographics library
6  *
7  * Copyright (C) 2002 Niels Möller
8  *  
9  * The nettle library is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or (at your
12  * option) any later version.
13  * 
14  * The nettle library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17  * License for more details.
18  * 
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with the nettle library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02111-1301, USA.
23  */
24    
25 #if HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <assert.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #ifdef WIN32
36 #include <fcntl.h>
37 #endif
38
39 /* string.h must be included before gmp.h */
40 #include "bignum.h"
41 #include "buffer.h"
42 #include "macros.h"
43 #include "rsa.h"
44 #include "yarrow.h"
45
46 #include "io.h"
47 #include "rsa-session.h"
48
49 #include "getopt.h"
50
51 void
52 rsa_session_set_encrypt_key(struct rsa_session *ctx,
53                             const struct rsa_session_info *key)
54 {
55   const uint8_t *aes_key = SESSION_AES_KEY(key);
56   const uint8_t *iv = SESSION_IV(key);
57   const uint8_t *hmac_key = SESSION_HMAC_KEY(key);
58   
59   aes_set_encrypt_key(&ctx->aes.ctx, AES_KEY_SIZE, aes_key);
60   CBC_SET_IV(&ctx->aes, iv);
61   hmac_sha1_set_key(&ctx->hmac, SHA1_DIGEST_SIZE, hmac_key);
62 }
63
64 static int
65 write_uint32(FILE *f, uint32_t n)
66 {
67   uint8_t buffer[4];
68   WRITE_UINT32(buffer, n);
69
70   return write_string(f, sizeof(buffer), buffer);
71 }
72
73 static int
74 write_version(FILE *f)
75 {
76   return write_uint32(f, 1);
77 }
78
79 static int
80 write_bignum(FILE *f, mpz_t x)
81 {
82   unsigned size = nettle_mpz_sizeinbase_256_u(x);
83   uint8_t *p;
84   int res;
85   
86   if (!write_uint32(f, size))
87     return 0;
88   
89   p = xalloc(size);
90   nettle_mpz_get_str_256(size, p, x);
91
92   res = write_string(f, size, p);
93   free(p);
94   return res;
95 }
96
97 #define BLOCK_SIZE (AES_BLOCK_SIZE * 100)
98
99 static int
100 process_file(struct rsa_session *ctx,
101              FILE *in, FILE *out)
102 {
103   uint8_t buffer[BLOCK_SIZE + SHA1_DIGEST_SIZE];
104
105   for (;;)
106     {
107       size_t size = fread(buffer, 1, BLOCK_SIZE, in);
108       hmac_sha1_update(&ctx->hmac, size, buffer);
109
110       if (size < BLOCK_SIZE)
111         {
112           unsigned leftover;
113           unsigned padding;
114
115           if (ferror(in))
116             {
117               werror("Reading input failed: %s\n", strerror(errno));
118               return 0;
119             }
120           
121           leftover = size % AES_BLOCK_SIZE;
122           padding = AES_BLOCK_SIZE - leftover;
123
124           assert (size + padding <= BLOCK_SIZE);
125           
126           if (padding > 1)
127             yarrow256_random(&ctx->yarrow, padding - 1, buffer + size);
128
129           size += padding;
130
131           buffer[size - 1] = padding;
132           CBC_ENCRYPT(&ctx->aes, aes_encrypt, size, buffer, buffer);
133
134           assert (size + SHA1_DIGEST_SIZE <= sizeof(buffer));
135
136           hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, buffer + size);
137           size += SHA1_DIGEST_SIZE;
138
139           if (!write_string(out, size, buffer))
140             {
141               werror("Writing output failed: %s\n", strerror(errno));
142               return 0;
143             }
144           return 1;
145         }
146
147       CBC_ENCRYPT(&ctx->aes, aes_encrypt, size, buffer, buffer);
148       if (!write_string(out, size, buffer))
149         {
150           werror("Writing output failed: %s\n", strerror(errno));
151           return 0;
152         }
153     }
154 }
155
156 static void
157 usage (FILE *out)
158 {
159   fprintf (out, "Usage: rsa-encrypt [OPTIONS] PUBLIC-KEY < cleartext\n"
160            "Options:\n"
161            "   -r, --random=FILE   seed file for randomness generator\n"
162            "       --help          display this help\n");  
163 }
164
165 int
166 main(int argc, char **argv)
167 {
168   struct rsa_session ctx;
169   struct rsa_session_info info;
170   
171   struct rsa_public_key key;
172   mpz_t x;
173   
174   int c;
175   const char *random_name = NULL;
176
177   enum { OPT_HELP = 300 };
178   
179   static const struct option options[] =
180     {
181       /* Name, args, flag, val */
182       { "help", no_argument, NULL, OPT_HELP },
183       { "random", required_argument, NULL, 'r' },
184       { NULL, 0, NULL, 0}
185     };
186   
187   while ( (c = getopt_long(argc, argv, "o:r:", options, NULL)) != -1)
188     switch (c)
189       {
190       case 'r':
191         random_name = optarg;
192         break;
193         
194       case '?':
195         return EXIT_FAILURE;
196
197       case OPT_HELP:
198         usage(stdout);
199         return EXIT_SUCCESS;
200       default:
201         abort();
202       }
203
204   argv += optind;
205   argc -= optind;
206
207   if (argc != 1)
208     {
209       usage (stderr);
210       return EXIT_FAILURE;
211     }
212
213   rsa_public_key_init(&key);
214   
215   if (!read_rsa_key(argv[0], &key, NULL))
216     {
217       werror("Invalid key\n");
218       return EXIT_FAILURE;
219     }
220
221   /* NOTE: No sources */
222   yarrow256_init(&ctx.yarrow, 0, NULL);
223   
224   /* Read some data to seed the generator */
225   if (!simple_random(&ctx.yarrow, random_name))
226     {
227       werror("Initialization of randomness generator failed.\n");
228       return EXIT_FAILURE;
229     }
230
231   WRITE_UINT32(SESSION_VERSION(&info), RSA_VERSION);
232   
233   yarrow256_random(&ctx.yarrow, sizeof(info.key) - 4, info.key + 4);
234
235   rsa_session_set_encrypt_key(&ctx, &info);
236   
237 #ifdef WIN32
238   _setmode(0, O_BINARY);
239   _setmode(1, O_BINARY);
240 #endif
241
242   write_version(stdout);
243   
244   mpz_init(x);
245
246   if (!rsa_encrypt(&key,
247                    &ctx.yarrow, (nettle_random_func *) yarrow256_random,
248                    sizeof(info.key), info.key, 
249                    x))
250     {
251       werror("RSA encryption failed.\n");
252       return EXIT_FAILURE;
253     }
254
255   write_bignum(stdout, x);
256
257   mpz_clear (x);
258
259   if (!process_file(&ctx,
260                     stdin, stdout))
261     return EXIT_FAILURE;
262
263   rsa_public_key_clear(&key);
264
265   return EXIT_SUCCESS;
266 }