Revert "Merge branch 'upstream' into tizen"
[platform/upstream/nettle.git] / examples / rsa-decrypt.c
1 /* rsa-decrypt.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 <ctype.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #ifdef WIN32
35 #include <fcntl.h>
36 #endif
37
38 /* string.h must be included before gmp.h */
39 #include "aes.h"
40 #include "bignum.h"
41 #include "buffer.h"
42 #include "cbc.h"
43 #include "hmac.h"
44 #include "macros.h"
45 #include "rsa.h"
46 #include "yarrow.h"
47
48 #include "io.h"
49 #include "rsa-session.h"
50
51 void
52 rsa_session_set_decrypt_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_decrypt_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 read_uint32(FILE *f, uint32_t *n)
66 {
67   uint8_t buf[4];
68   if (fread(buf, 1, sizeof(buf), f) != sizeof(buf))
69     return 0;
70
71   *n = READ_UINT32(buf);
72   return 1;
73 }
74
75 static int
76 read_version(FILE *f)
77 {
78   uint32_t version;
79   return read_uint32(f, &version) && version == RSA_VERSION;
80 }
81
82 static int
83 read_bignum(FILE *f, mpz_t x)
84 {
85   uint32_t size;
86   if (read_uint32(f, &size)
87       && size < 1000)
88     {
89       uint8_t *p = xalloc(size);
90       if (fread(p, 1, size, f) != size)
91         {
92           free(p);
93           return 0;
94         }
95
96       nettle_mpz_set_str_256_u(x, size, p);
97       free(p);
98
99       return 1;
100     }
101   return 0;
102 }
103
104 struct process_ctx
105 {
106   struct CBC_CTX(struct aes_ctx, AES_BLOCK_SIZE) aes;
107   struct hmac_sha1_ctx hmac;
108   struct yarrow256_ctx yarrow;
109 };
110
111 #define BUF_SIZE (100 * AES_BLOCK_SIZE)
112
113 /* Trailing data that needs special processing */
114 #define BUF_FINAL (AES_BLOCK_SIZE + SHA1_DIGEST_SIZE)
115
116 static int
117 process_file(struct rsa_session *ctx,
118              FILE *in, FILE *out)
119 {
120   uint8_t buffer[BUF_SIZE + BUF_FINAL];
121   uint8_t digest[SHA1_DIGEST_SIZE];
122   size_t size;
123   unsigned padding;
124
125   size = fread(buffer, 1, BUF_FINAL, in);
126   if (size < BUF_FINAL)
127     {
128       if (ferror(in))
129         werror("Reading input failed: %s\n", strerror(errno));
130       else
131         werror("Unexpected EOF on input.\n");
132       return 0;
133     }
134
135   do
136     {
137       size = fread(buffer + BUF_FINAL, 1, BUF_SIZE, in);
138
139       if (size < BUF_SIZE && ferror(in))
140         {
141           werror("Reading input failed: %s\n", strerror(errno));
142           return 0;
143         }
144
145       if (size % AES_BLOCK_SIZE != 0)
146         {
147           werror("Unexpected EOF on input.\n");
148           return 0;
149         }
150
151       if (size)
152         {
153           CBC_DECRYPT(&ctx->aes, aes_decrypt, size, buffer, buffer);
154           hmac_sha1_update(&ctx->hmac, size, buffer);
155           if (!write_string(out, size, buffer))
156             {
157               werror("Writing output failed: %s\n", strerror(errno));
158               return 0;
159             }
160           memmove(buffer, buffer + size, BUF_FINAL);
161         }
162     }
163   while (size == BUF_SIZE);
164
165   /* Decrypt final block */
166   CBC_DECRYPT(&ctx->aes, aes_decrypt, AES_BLOCK_SIZE, buffer, buffer);
167   padding = buffer[AES_BLOCK_SIZE - 1];
168   if (padding > AES_BLOCK_SIZE)
169     {
170       werror("Decryption failed: Invalid padding.\n");
171       return 0;
172     }
173
174   if (padding < AES_BLOCK_SIZE)
175     {
176       unsigned leftover = AES_BLOCK_SIZE - padding;
177       hmac_sha1_update(&ctx->hmac, leftover, buffer);
178       if (!write_string(out, leftover, buffer))
179         {
180           werror("Writing output failed: %s\n", strerror(errno));
181           return 0;
182         }
183     }
184   hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, digest);
185   if (memcmp(digest, buffer + AES_BLOCK_SIZE, SHA1_DIGEST_SIZE) != 0)
186     {
187       werror("Decryption failed: Invalid mac.\n");
188       return 0;
189     }
190   
191   return 1;
192 }
193
194 int
195 main(int argc, char **argv)
196 {
197   struct rsa_private_key key;
198   struct rsa_session ctx;
199   struct rsa_session_info session;
200
201   unsigned length;
202   mpz_t x;
203
204   mpz_init(x);
205   
206   if (argc != 2)
207     {
208       werror("Usage: rsa-decrypt PRIVATE-KEY < ciphertext\n");
209       return EXIT_FAILURE;
210     }
211
212   rsa_private_key_init(&key);
213   
214   if (!read_rsa_key(argv[1], NULL, &key))
215     {
216       werror("Invalid key\n");
217       return EXIT_FAILURE;
218     }
219
220 #ifdef WIN32
221   _setmode(0, O_BINARY);
222   _setmode(1, O_BINARY);
223 #endif
224
225   if (!read_version(stdin))
226     {
227       werror("Bad version number in input file.\n");
228       return EXIT_FAILURE;
229     }
230
231   if (!read_bignum(stdin, x))
232     {
233       werror("Bad rsa header in input file.\n");
234       return EXIT_FAILURE;
235     }
236
237   length = sizeof(session.key);
238   if (!rsa_decrypt(&key, &length, session.key, x) || length != sizeof(session.key))
239     {
240       werror("Failed to decrypt rsa header in input file.\n");
241       return EXIT_FAILURE;      
242     }
243   mpz_clear(x);
244   
245   rsa_session_set_decrypt_key(&ctx, &session);
246
247   if (!process_file(&ctx,
248                     stdin, stdout))
249     return EXIT_FAILURE;
250   
251   rsa_private_key_clear(&key);
252
253   return EXIT_SUCCESS;
254 }