Added OpenPGP library to lib/silcpgp
[crypto.git] / lib / silcpgp / silcpgp_seckey.c
1 /*
2
3   silcpgp_seckey.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2007 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silccrypto.h"
21 #include "rsa.h"
22 #include "dsa.h"
23
24 /*************************** Private Key Routines ***************************/
25
26 /* Decode OpenPGP Secret Key packet */
27
28 int silc_pgp_packet_private_key_decode(unsigned char *key, SilcUInt32 key_len,
29                                        const char *passphrase,
30                                        SilcUInt32 passphrase_len,
31                                        SilcPGPPrivateKey privkey)
32 {
33   SilcBufferStruct keybuf;
34   SilcPGPPublicKey pubkey = NULL;
35   unsigned char *iv, *salt = NULL, *dec = NULL;
36   unsigned char *dec_key;
37   SilcUInt32 iv_len = 0;
38   SilcUInt16 pcksum;
39   SilcUInt8 s2k_usage, s2k_count;
40   SilcCipher cipher = NULL;
41   int ret, ret_len;
42
43   SILC_LOG_DEBUG(("Parsing OpenPGP private key"));
44
45   if (!key || !key_len)
46     return 0;
47   silc_buffer_set(&keybuf, key, key_len);
48
49   SILC_LOG_HEXDUMP(("OpenPGP private key"), key, key_len);
50
51   pubkey = silc_calloc(1, sizeof(*pubkey));
52   if (!pubkey) {
53     silc_free(privkey);
54     return 0;
55   }
56
57   /* Parse public key from the private key */
58   ret = silc_pgp_packet_public_key_decode(key, key_len, pubkey);
59   if (!ret) {
60     SILC_LOG_DEBUG(("Malformed private key"));
61     goto err;
62   }
63   if (!silc_buffer_pull(&keybuf, ret))
64     goto err;
65
66   if (silc_buffer_len(&keybuf) < 12)
67     goto err;
68
69   /* Decode algorithm info */
70   s2k_usage = keybuf.data[0];
71   silc_buffer_pull(&keybuf, 1);
72   switch (s2k_usage) {
73   case 0:
74     /* Plaintext private key */
75     SILC_LOG_DEBUG(("Private key is not encrypted"));
76     break;
77
78   case 254:
79   case 255:
80     /* Encrypted, string-to-key (S2K) specifier present */
81     if (silc_buffer_unformat(&keybuf,
82                              SILC_STR_ADVANCE,
83                              SILC_STR_UINT8(&privkey->cipher),
84                              SILC_STR_UINT8(&privkey->s2k_type),
85                              SILC_STR_UINT8(&privkey->s2k_hash),
86                              SILC_STR_END) < 0) {
87       SILC_LOG_DEBUG(("Malformed S2K specifier in private key"));
88       goto err;
89     }
90
91     SILC_LOG_DEBUG(("Private key S2K type %d", privkey->s2k_type));
92
93     switch (privkey->s2k_type) {
94     case SILC_PGP_S2K_SIMPLE:
95       /* Simple S2K */
96       iv_len = 0;
97       break;
98
99     case SILC_PGP_S2K_SALTED:
100       /* Salted S2K */
101       if (silc_buffer_unformat(&keybuf,
102                                SILC_STR_ADVANCE,
103                                SILC_STR_DATA(&salt, 8),
104                                SILC_STR_END) < 0) {
105         SILC_LOG_DEBUG(("Malformed S2K specifier in private key"));
106         goto err;
107       }
108       break;
109
110     case SILC_PGP_S2K_ITERATED_SALTED:
111       /* Iterated and salted S2K */
112       if (silc_buffer_unformat(&keybuf,
113                                SILC_STR_ADVANCE,
114                                SILC_STR_DATA(&salt, 8),
115                                SILC_STR_UINT8(&s2k_count),
116                                SILC_STR_END) < 0) {
117         SILC_LOG_DEBUG(("Malformed S2K specifier in private key"));
118         goto err;
119       }
120
121       /* Get the iterator octet count, formula comes from the RFC */
122       privkey->s2k_count = ((SilcUInt32)16 +
123                             (s2k_count & 15)) << ((s2k_count >> 4) + 6);
124       break;
125
126     default:
127       SILC_LOG_DEBUG(("Malformed private key"));
128       goto err;
129     }
130
131     break;
132
133   default:
134     /* Encrypted with given algorithm */
135     privkey->cipher = keybuf.data[0];
136     silc_buffer_pull(&keybuf, 1);
137     break;
138   }
139
140   ret_len = silc_buffer_headlen(&keybuf);
141
142   /* Decrypt */
143   if (privkey->cipher) {
144     cipher = silc_pgp_cipher_alloc(privkey->cipher);
145     if (!cipher)
146       goto err;
147
148     iv_len = silc_cipher_get_iv_len(cipher);
149
150     /* Get IV */
151     if (!silc_buffer_unformat(&keybuf,
152                               SILC_STR_ADVANCE,
153                               SILC_STR_DATA(&iv, iv_len),
154                               SILC_STR_END)) {
155       SILC_LOG_DEBUG(("Malformed private key, IV not present"));
156       goto err;
157     }
158     ret_len += iv_len;
159
160     SILC_LOG_HEXDUMP(("IV, iv_len %d", iv_len), iv, iv_len);
161
162     /* Generate decryption key from passphrase */
163     dec_key = silc_pgp_s2k(privkey->s2k_type, privkey->s2k_hash, passphrase,
164                            passphrase_len, silc_cipher_get_key_len(cipher) / 8,
165                            salt, privkey->s2k_count, NULL);
166     if (!dec_key)
167       goto err;
168
169     SILC_LOG_HEXDUMP(("S2K"), dec_key, silc_cipher_get_key_len(cipher) / 8);
170
171     /* Set decryption key */
172     silc_cipher_set_key(cipher, dec_key, silc_cipher_get_key_len(cipher),
173                         FALSE);
174     silc_cipher_set_iv(cipher, iv);
175
176     /* Decrypt the private key */
177     SILC_LOG_DEBUG(("Decrypting private key"));
178     dec = silc_memdup(silc_buffer_data(&keybuf), silc_buffer_len(&keybuf));
179     if (!dec)
180       goto err;
181     silc_buffer_set(&keybuf, dec, silc_buffer_len(&keybuf));
182
183     if (pubkey->version >= 4) {
184       silc_cipher_decrypt(cipher, keybuf.data, keybuf.data,
185                           silc_buffer_len(&keybuf), NULL);
186     } else {
187       /* Versions 2 and 3 */
188       /* Support may be added for these at some point. */
189       SILC_LOG_ERROR(("Version %d encrypted private keys not supported",
190                       pubkey->version));
191       goto err;
192     }
193   }
194
195   /* Verify checksum to see if decryption succeeded */
196   if (s2k_usage == 254) {
197     SilcHash sha1;
198     unsigned char cksum_hash[20], pcksum_hash[20];
199
200     if (!silc_buffer_push_tail(&keybuf, 20)) {
201       SILC_LOG_DEBUG(("Malformed private key, checksum not present"));
202       goto err;
203     }
204
205     memcpy(pcksum_hash, keybuf.tail, 20);
206
207     if (!silc_hash_alloc("sha1", &sha1))
208       goto err;
209     silc_hash_init(sha1);
210     silc_hash_update(sha1, silc_buffer_data(&keybuf),
211                      silc_buffer_len(&keybuf));
212     silc_hash_final(sha1, cksum_hash);
213     silc_hash_free(sha1);
214
215     /* Verify */
216     if (memcmp(cksum_hash, pcksum_hash, sizeof(cksum_hash))) {
217       SILC_LOG_DEBUG(("Private key checksum invalid, decryption failed"));
218       goto err;
219     }
220
221     ret_len += 20;
222   } else {
223     SilcUInt16 cksum = 0;
224     int i;
225
226     if (silc_buffer_unformat(&keybuf,
227                              SILC_STR_ADVANCE,
228                              SILC_STR_UINT16(&pcksum),
229                              SILC_STR_END) < 0) {
230       SILC_LOG_DEBUG(("Malformed private key, checksum not present"));
231       goto err;
232     }
233
234     for (i = 0; i < silc_buffer_len(&keybuf); i++)
235       cksum = (cksum + keybuf.data[i]) % 0x10000;
236
237     /* Verify */
238     if (cksum != pcksum) {
239       SILC_LOG_DEBUG(("Private key checksum invalid, decryption failed"));
240       goto err;
241     }
242
243     ret_len += 2;
244   }
245
246   /* Import the algorithm private key */
247   ret = pubkey->pkcs->import_private_key(pubkey->pkcs,
248                                          silc_buffer_data(&keybuf),
249                                          silc_buffer_len(&keybuf),
250                                          &privkey->private_key);
251   if (!ret) {
252     SILC_LOG_DEBUG(("Malformed private key"));
253     goto err;
254   }
255
256   silc_free(dec);
257
258   privkey->public_key = pubkey;
259
260   return ret_len + ret;
261
262  err:
263   if (pubkey)
264     silc_pgp_public_key_free(pubkey);
265   silc_free(dec);
266   return 0;
267 }
268
269 /* Decode private key from PGP packets */
270
271 SilcBool silc_pgp_private_key_decode(SilcList *list,
272                                      const char *passphrase,
273                                      SilcUInt32 passphrase_len,
274                                      SilcPGPPrivateKey *ret_private_key)
275 {
276   SilcPGPPrivateKey privkey, subkey;
277   unsigned char *data;
278   SilcUInt32 data_len;
279   SilcPGPPacket prv, packet;
280
281   SILC_LOG_DEBUG(("Parse OpenPGP private key"));
282
283   privkey = silc_calloc(1, sizeof(*privkey));
284   if (!privkey)
285     goto err;
286
287   /* First packet must be private key packet */
288   prv = silc_list_get(*list);
289   if (!prv)
290     goto err;
291   if (silc_pgp_packet_get_tag(prv) != SILC_PGP_PACKET_SECKEY &&
292       silc_pgp_packet_get_tag(prv) != SILC_PGP_PACKET_SECKEY_SUB)
293     goto err;
294
295   /* Parse the private key */
296   data = silc_pgp_packet_get_data(prv, &data_len);
297   if (!silc_pgp_packet_private_key_decode(data, data_len, passphrase,
298                                           passphrase_len, privkey))
299     goto err;
300
301   /* Parse any and all packets until we hit end of the packets or next
302      private key in the list.  We simply copy the raw data, and actual
303      parsing is done later if and when the packets are needed. */
304   if (silc_pgp_packet_get_tag(prv) == SILC_PGP_PACKET_SECKEY) {
305     silc_list_init(privkey->packets, struct SilcPGPPacketStruct, next);
306
307     /* Copy the raw private key packet */
308     packet = silc_pgp_packet_copy(prv);
309     if (packet)
310       silc_list_add(privkey->packets, packet);
311
312     while ((packet = silc_list_get(*list))) {
313       SILC_LOG_DEBUG(("Adding %d (%s) packet to private key",
314                       silc_pgp_packet_get_tag(packet),
315                       silc_pgp_packet_name(silc_pgp_packet_get_tag(packet))));
316
317       switch (silc_pgp_packet_get_tag(packet)) {
318
319       case SILC_PGP_PACKET_SECKEY:
320         /* Next private key, stop decoding.  Set list pointer so that the list
321            points to the next private key. */
322         list->current = packet;
323         break;
324
325       case SILC_PGP_PACKET_SECKEY_SUB:
326         /* Parse subkeys recursively */
327         list->current = packet;
328         if (!silc_pgp_private_key_decode(list, passphrase,
329                                          passphrase_len, &subkey))
330           goto err;
331
332         if (!privkey->subkeys) {
333           privkey->subkeys = silc_dlist_init();
334           if (!privkey->subkeys)
335             goto err;
336         }
337         silc_dlist_add(privkey->subkeys, subkey);
338
339       default:
340         /* Copy packet to the private key */
341         packet = silc_pgp_packet_copy(packet);
342         if (packet)
343           silc_list_add(privkey->packets, packet);
344         break;
345       }
346     }
347   }
348
349   if (ret_private_key)
350     *ret_private_key = privkey;
351
352   return TRUE;
353
354  err:
355   silc_free(privkey);
356   return FALSE;
357 }
358
359 /* Free private key */
360
361 void silc_pgp_private_key_free(SilcPGPPrivateKey private_key)
362 {
363   SilcPGPPrivateKey p;
364   SilcPGPPacket packet;
365
366   if (private_key->public_key && private_key->public_key->pkcs)
367     private_key->public_key->pkcs->private_key_free(private_key->
368                                                     public_key->pkcs,
369                                                     private_key->private_key);
370
371   silc_pgp_public_key_free(private_key->public_key);
372
373   if (private_key->subkeys) {
374     silc_dlist_start(private_key->subkeys);
375     while ((p = silc_dlist_get(private_key->subkeys)))
376       silc_pgp_private_key_free(p);
377     silc_dlist_uninit(private_key->subkeys);
378   }
379
380   silc_list_start(private_key->packets);
381   while ((packet = silc_list_get(private_key->packets)))
382     silc_pgp_packet_free(packet);
383
384   silc_free(private_key);
385 }