Initialize Tizen 2.3
[external/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., 59 Temple Place - Suite 330, Boston,
22  * MA 02111-1307, USA.
23  */
24    
25 #if HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <ctype.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 /* string.h must be included before gmp.h */
36 #include "bignum.h"
37 #include "buffer.h"
38 #include "macros.h"
39 #include "rsa.h"
40 #include "yarrow.h"
41
42 #include "io.h"
43 #include "rsa-session.h"
44
45 #include "getopt.h"
46
47 void
48 rsa_session_set_encrypt_key(struct rsa_session *ctx,
49                             const struct rsa_session_info *key)
50 {
51   const uint8_t *aes_key = SESSION_AES_KEY(key);
52   const uint8_t *iv = SESSION_IV(key);
53   const uint8_t *hmac_key = SESSION_HMAC_KEY(key);
54   
55   aes_set_encrypt_key(&ctx->aes.ctx, AES_KEY_SIZE, aes_key);
56   CBC_SET_IV(&ctx->aes, iv);
57   hmac_sha1_set_key(&ctx->hmac, SHA1_DIGEST_SIZE, hmac_key);
58 }
59
60 static int
61 write_uint32(FILE *f, uint32_t n)
62 {
63   uint8_t buffer[4];
64   WRITE_UINT32(buffer, n);
65
66   return write_string(f, sizeof(buffer), buffer);
67 }
68
69 static int
70 write_version(FILE *f)
71 {
72   return write_uint32(f, 1);
73 }
74
75 static int
76 write_bignum(FILE *f, mpz_t x)
77 {
78   unsigned size = nettle_mpz_sizeinbase_256_u(x);
79   uint8_t *p;
80   int res;
81   
82   if (!write_uint32(f, size))
83     return 0;
84   
85   p = xalloc(size);
86   nettle_mpz_get_str_256(size, p, x);
87
88   res = write_string(f, size, p);
89   free(p);
90   return res;
91 }
92
93 static int
94 process_file(struct rsa_session *ctx,
95              FILE *in, FILE *out)
96 {
97   uint8_t buffer[AES_BLOCK_SIZE * 100];
98   unsigned leftover;
99   unsigned padding;
100
101   padding = leftover = 0;
102
103   for (;;)
104     {
105       size_t size = fread(buffer, 1, sizeof(buffer), in);
106       if (ferror(in))
107         {
108           werror("Reading input failed: %s\n", strerror(errno));
109           return 0;
110         }
111
112       hmac_sha1_update(&ctx->hmac, size, buffer);
113       if (size < sizeof(buffer))
114         {
115           /* Setting padding != ends the loop */
116           leftover = size % AES_BLOCK_SIZE;
117           padding = AES_BLOCK_SIZE - leftover;
118           size -= leftover;
119
120           if (!size)
121             break;
122         }
123
124       CBC_ENCRYPT(&ctx->aes, aes_encrypt, size, buffer, buffer);
125       if (!write_string(out, size, buffer))
126         {
127           werror("Writing output failed: %s\n", strerror(errno));
128           return 0;
129         }
130
131       if (padding)
132         {
133           if (leftover)
134             memcpy(buffer, buffer + size, leftover);
135
136           break;
137         }
138     }
139   if (padding > 1)
140     yarrow256_random(&ctx->yarrow, padding - 1, buffer + leftover);
141
142   buffer[AES_BLOCK_SIZE - 1] = padding;
143   CBC_ENCRYPT(&ctx->aes, aes_encrypt, AES_BLOCK_SIZE, buffer, buffer);
144   hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, buffer + AES_BLOCK_SIZE);
145
146   if (!write_string(out, AES_BLOCK_SIZE + SHA1_DIGEST_SIZE, buffer))
147     {
148       werror("Writing output failed: %s\n", strerror(errno));
149       return 0;
150     }
151
152   return 1;
153 }
154
155 int
156 main(int argc, char **argv)
157 {
158   struct rsa_session ctx;
159   struct rsa_session_info info;
160   
161   struct rsa_public_key key;
162   mpz_t x;
163   
164   int c;
165   const char *random_name = NULL;
166   
167   while ( (c = getopt(argc, argv, "o:r:")) != -1)
168     switch (c)
169       {
170       case 'r':
171         random_name = optarg;
172         break;
173         
174       case '?':
175         if (isprint (optopt))
176           werror("Unknown option `-%c'.\n", optopt);
177         else
178           werror("Unknown option character `\\x%x'.\n",
179                   optopt);
180         return EXIT_FAILURE;
181       default:
182         abort();
183       }
184
185   argv += optind;
186   argc -= optind;
187
188   if (argc != 1)
189     {
190       werror("Usage: rsa-encrypt [-r random-file] PUBLIC-KEY < cleartext\n");
191       return EXIT_FAILURE;
192     }
193
194   rsa_public_key_init(&key);
195   
196   if (!read_rsa_key(argv[0], &key, NULL))
197     {
198       werror("Invalid key\n");
199       return EXIT_FAILURE;
200     }
201
202   /* NOTE: No sources */
203   yarrow256_init(&ctx.yarrow, 0, NULL);
204   
205   /* Read some data to seed the generator */
206   if (!simple_random(&ctx.yarrow, random_name))
207     {
208       werror("Initialization of randomness generator failed.\n");
209       return EXIT_FAILURE;
210     }
211
212   WRITE_UINT32(SESSION_VERSION(&info), RSA_VERSION);
213   
214   yarrow256_random(&ctx.yarrow, sizeof(info.key) - 4, info.key + 4);
215
216   rsa_session_set_encrypt_key(&ctx, &info);
217   
218   write_version(stdout);
219   
220   mpz_init(x);
221
222   if (!rsa_encrypt(&key,
223                    &ctx.yarrow, (nettle_random_func *) yarrow256_random,
224                    sizeof(info.key), info.key, 
225                    x))
226     {
227       werror("RSA encryption failed.\n");
228       return EXIT_FAILURE;
229     }
230
231   write_bignum(stdout, x);
232   
233   if (!process_file(&ctx,
234                     stdin, stdout))
235     return EXIT_FAILURE;
236   
237   rsa_public_key_clear(&key);
238
239   return EXIT_SUCCESS;
240 }