~ubuntu-branches/ubuntu/saucy/nettle/saucy-proposed

« back to all changes in this revision

Viewing changes to examples/rsa-decrypt.c

  • Committer: Bazaar Package Importer
  • Author(s): Marek Habersack
  • Date: 2004-05-04 15:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20040504155602-7jbhw5mabvwksl3j
Tags: upstream-1.10
Import upstream version 1.10

Show diffs side-by-side

added added

removed removed

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