root/openpgpsdk/trunk/src/lib/adv_create.c

Revision 560 (checked in by rachel, 5 years ago)

Implemented writing of armoured transferable public and private keys.
Refactored armoured code to remove duplication.

Line 
1 /** \file
2  */
3
4 #include <openssl/cast.h>
5
6 #include <openpgpsdk/armour.h>
7 #include <openpgpsdk/create.h>
8 #include <openpgpsdk/keyring.h>
9 #include <openpgpsdk/memory.h>
10 #include <openpgpsdk/random.h>
11 #include <openpgpsdk/readerwriter.h>
12 #include "keyring_local.h"
13 #include <openpgpsdk/packet.h>
14 #include <openpgpsdk/util.h>
15 #include <openpgpsdk/std_print.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <fcntl.h>
19 #ifndef WIN32
20 #include <unistd.h>
21 #endif
22
23 #include <openpgpsdk/final.h>
24
25 static int debug=0;
26
27 static ops_boolean_t writer_info_finalise(ops_error_t **errors,
28                                           ops_writer_info_t *winfo);
29
30 /*
31  * return true if OK, otherwise false
32  */
33 static ops_boolean_t base_write(const void *src,unsigned length,
34                                 ops_create_info_t *info)
35     {
36     return info->winfo.writer(src,length,&info->errors,&info->winfo);
37     }
38
39 /**
40  * \ingroup Create
41  *
42  * \param src
43  * \param length
44  * \param info
45  * \return 1 if OK, otherwise 0
46  */
47
48 ops_boolean_t ops_write(const void *src,unsigned length,
49                         ops_create_info_t *info)
50     {
51     return base_write(src,length,info);
52     }
53
54 /**
55  * \ingroup Create
56  * \param n
57  * \param length
58  * \param info
59  * \return ops_true if OK, otherwise ops_false
60  */
61
62 ops_boolean_t ops_write_scalar(unsigned n,unsigned length,
63                                ops_create_info_t *info)
64     {
65     while(length-- > 0)
66         {
67         unsigned char c[1];
68
69         c[0]=n >> (length*8);
70         if(!base_write(c,1,info))
71             return ops_false;
72         }
73     return ops_true;
74     }
75
76 /**
77  * \ingroup Create
78  * \param bn
79  * \param info
80  * \return 1 if OK, otherwise 0
81  * \todo This statement about the return value is true based on the assumption
82  *      that ops_true=1. Tidy this assumption up.
83  */
84
85 ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *info)
86     {
87     unsigned char buf[8192];
88     int bits=BN_num_bits(bn);
89
90     assert(bits <= 65535);
91     BN_bn2bin(bn,buf);
92     return ops_write_scalar(bits,2,info)
93         && ops_write(buf,(bits+7)/8,info);
94     }
95
96 /**
97  * \ingroup Create
98  * \param tag
99  * \param info
100  * \return 1 if OK, otherwise 0
101  */
102
103 ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *info)
104     {
105     unsigned char c[1];
106
107     c[0]=tag|OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT;
108
109     return base_write(c,1,info);
110     }
111
112 /**
113  * \ingroup Create
114  * \param length
115  * \param info
116  * \return 1 if OK, otherwise 0
117  */
118
119 ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *info)
120     {
121     unsigned char c[2];
122
123     if(length < 192)
124         {
125         c[0]=length;
126         return base_write(c,1,info);
127         }
128     else if(length < 8384)
129         {
130         c[0]=((length-192) >> 8)+192;
131         c[1]=(length-192)%256;
132         return base_write(c,2,info);
133         }
134     return ops_write_scalar(0xff,1,info) && ops_write_scalar(length,4,info);
135     }
136
137 /**
138  * \ingroup Create
139  * \param length
140  * \param type
141  * \param info
142  * \return 1 if OK, otherwise 0
143  */
144
145 ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type,
146                                   ops_create_info_t *info)
147     {
148     return ops_write_length(length,info)
149         && ops_write_scalar(type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE,1,info);
150     }
151
152 /* XXX: the general idea of _fast_ is that it doesn't copy stuff
153  * the safe (i.e. non _fast_) version will, and so will also need to
154  * be freed. */
155
156 /**
157  * \ingroup Create
158  *
159  * ops_fast_create_user_id() sets id->user_id to the given user_id.
160  * This is fast because it is only copying a char*. However, if user_id
161  * is changed or freed in the future, this could have injurious results.
162  * \param id
163  * \param user_id
164  */
165
166 void ops_fast_create_user_id(ops_user_id_t *id,unsigned char *user_id)
167     {
168     id->user_id=user_id;
169     }
170
171 /**
172  * \ingroup Create
173  *
174  * Writes a User Id from the information held in id and info
175  *
176  * \param id
177  * \param info
178  * \return Return value from ops_write() unless call to ops_write_ptag() or ops_write_length() failed before it was called, in which case returns 0
179  * \todo tidy up that return value description!
180  */
181 ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id,
182                                        ops_create_info_t *info)
183     {
184     return ops_write_ptag(OPS_PTAG_CT_USER_ID,info)
185         && ops_write_length(strlen((char *)id->user_id),info)
186         && ops_write(id->user_id,strlen((char *)id->user_id),info);
187     }
188
189 /**
190  * \ingroup Create
191  *
192  * Write User Id
193  *
194  * \param user_id
195  * \param info
196  *
197  * \return return value from ops_write_struct_user_id()
198  * \todo better descr of return value
199  */
200 ops_boolean_t ops_write_user_id(const unsigned char *user_id,ops_create_info_t *info)
201     {
202     ops_user_id_t id;
203
204     id.user_id=(unsigned char *)user_id;
205     return ops_write_struct_user_id(&id,info);
206     }
207
208 static unsigned mpi_length(const BIGNUM *bn)
209     {
210     return 2+(BN_num_bits(bn)+7)/8;
211     }
212
213 static unsigned public_key_length(const ops_public_key_t *key)
214     {
215     switch(key->algorithm)
216         {
217     case OPS_PKA_RSA:
218         return mpi_length(key->key.rsa.n)+mpi_length(key->key.rsa.e);
219
220     default:
221         assert(!"unknown key algorithm");
222         }
223     /* not reached */
224     return 0;
225     }
226
227 static unsigned secret_key_length(const ops_secret_key_t *key)
228     {
229     int l;
230
231     switch(key->public_key.algorithm)
232         {
233     case OPS_PKA_RSA:
234         l=mpi_length(key->key.rsa.d)+mpi_length(key->key.rsa.p)
235             +mpi_length(key->key.rsa.q)+mpi_length(key->key.rsa.u);
236         break;
237
238     default:
239         assert(!"unknown key algorithm");
240         }
241
242     return l+public_key_length(&key->public_key);
243     }
244
245 /**
246  * \ingroup Create
247  * \param key
248  * \param time
249  * \param n
250  * \param e
251 */
252 void ops_fast_create_rsa_public_key(ops_public_key_t *key,time_t time,
253                                     BIGNUM *n,BIGNUM *e)
254     {
255     key->version=4;
256     key->creation_time=time;
257     key->algorithm=OPS_PKA_RSA;
258     key->key.rsa.n=n;
259     key->key.rsa.e=e;
260     }
261
262 /* Note that we support v3 keys here because they're needed for
263  * for verification - the writer doesn't allow them, though */
264 static ops_boolean_t write_public_key_body(const ops_public_key_t *key,
265                                            ops_create_info_t *info)
266     {
267     if(!(ops_write_scalar(key->version,1,info)
268          && ops_write_scalar(key->creation_time,4,info)))
269         return ops_false;
270
271     if(key->version != 4 && !ops_write_scalar(key->days_valid,2,info))
272         return ops_false;
273
274     if(!ops_write_scalar(key->algorithm,1,info))
275         return ops_false;
276
277     switch(key->algorithm)
278         {
279     case OPS_PKA_DSA:
280         return ops_write_mpi(key->key.dsa.p,info)
281             && ops_write_mpi(key->key.dsa.q,info)
282             && ops_write_mpi(key->key.dsa.g,info)
283             && ops_write_mpi(key->key.dsa.y,info);
284
285     case OPS_PKA_RSA:
286     case OPS_PKA_RSA_ENCRYPT_ONLY:
287     case OPS_PKA_RSA_SIGN_ONLY:
288         return ops_write_mpi(key->key.rsa.n,info)
289             && ops_write_mpi(key->key.rsa.e,info);
290
291     case OPS_PKA_ELGAMAL:
292         return ops_write_mpi(key->key.elgamal.p,info)
293             && ops_write_mpi(key->key.elgamal.g,info)
294             && ops_write_mpi(key->key.elgamal.y,info);
295
296     default:
297         assert(0);
298         break;
299         }
300
301     /* not reached */
302     return ops_false;
303     }
304
305 typedef struct
306     {
307     ops_hash_algorithm_t hash_algorithm;
308     ops_hash_t hash;
309     unsigned char *hashed;
310     } skey_checksum_arg_t;
311
312 static ops_boolean_t skey_checksum_writer(const unsigned char *src, const unsigned length, ops_error_t **errors, ops_writer_info_t *winfo)
313     {
314     skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
315     ops_boolean_t rtn=ops_true;
316
317     // add contents to hash
318     arg->hash.add(&arg->hash, src, length);
319
320     // write to next stacked writer
321     rtn=ops_stacked_write(src,length,errors,winfo);
322
323     // tidy up and return
324     return rtn;
325     }
326
327 static ops_boolean_t skey_checksum_finaliser(ops_error_t **errors __attribute__((unused)), ops_writer_info_t *winfo)
328     {
329     skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
330     arg->hash.finish(&arg->hash, arg->hashed);
331     return ops_true;
332     }
333
334 static void skey_checksum_destroyer(ops_writer_info_t* winfo)
335     {
336     skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
337     free(arg);
338     }
339
340 void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey)
341     {
342     //    OPS_USED(info);
343     // XXX: push a SHA-1 checksum writer (and change s2k to 254).
344     skey_checksum_arg_t *arg=ops_mallocz(sizeof *arg);
345
346     // configure the arg
347     arg->hash_algorithm=skey->hash_algorithm;
348     arg->hashed=&skey->checkhash[0];
349
350     // init the hash
351     ops_hash_any(&arg->hash, arg->hash_algorithm);
352     arg->hash.init(&arg->hash);
353
354     ops_writer_push(cinfo, skey_checksum_writer, skey_checksum_finaliser, skey_checksum_destroyer, arg);
355     }
356  
357 /* Note that we support v3 keys here because they're needed for
358  * for verification - the writer doesn't allow them, though */
359 static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key,
360                                            const unsigned char* passphrase,
361                                            const size_t pplen,
362                                            ops_create_info_t *info)
363     {
364     /* RFC4880 Section 5.5.3 Secret-Key Packet Formats */
365
366     ops_crypt_t crypt;
367     ops_hash_t hash;
368     unsigned char hashed[OPS_SHA1_HASH_SIZE];
369     unsigned char session_key[CAST_KEY_LENGTH];
370     unsigned int done=0;
371     unsigned int i=0;
372
373     if(!write_public_key_body(&key->public_key,info))
374         return ops_false;
375
376     assert(key->s2k_usage==OPS_S2KU_ENCRYPTED_AND_HASHED); /* = 254 */
377     if(!ops_write_scalar(key->s2k_usage,1,info))
378         return ops_false;
379    
380     assert(key->algorithm==OPS_SA_CAST5);
381     if (!ops_write_scalar(key->algorithm,1,info))
382         return ops_false;
383
384     assert(key->s2k_specifier==OPS_S2KS_SIMPLE); // = 1 \todo should be salted or iterated-and-salted
385     if (!ops_write_scalar(key->s2k_specifier,1,info))
386         return ops_false;
387    
388     assert(key->hash_algorithm==OPS_HASH_SHA1);
389     if (!ops_write_scalar(key->hash_algorithm,1,info))
390         return ops_false;
391    
392     switch(key->s2k_specifier)
393         {
394     case OPS_S2KS_SIMPLE:
395         // nothing more to do
396         break;
397
398         /* \todo
399     case OPS_S2KS_SALTED:
400     // 8-octet salt value
401         break;
402
403     case OPS_S2KS_ITERATED_AND_SALTED:
404     // 8-octet salt value
405     // 1-octet count
406         break;
407         */
408
409     default:
410         fprintf(stderr,"invalid/unsupported s2k specifier %d\n", key->s2k_specifier);
411         assert(0);
412         }
413
414     if (!ops_write(&key->iv[0],ops_block_size(key->algorithm),info))
415         return ops_false;
416    
417     /* create the session key for encrypting the algorithm-specific fields */
418
419     switch(key->s2k_specifier)
420         {
421     case OPS_S2KS_SIMPLE:
422         // RFC4880: section 3.7.1.1
423
424         done=0;
425         for (i=0; done<CAST_KEY_LENGTH; i++ )
426             {
427             unsigned int j=0;
428             unsigned char zero=0;
429             int needed=CAST_KEY_LENGTH-done;
430             int use= needed < SHA_DIGEST_LENGTH ? needed : SHA_DIGEST_LENGTH;
431
432             ops_hash_any(&hash, key->hash_algorithm);
433             hash.init(&hash);
434            
435             // preload if iterating
436             for (j=0; j<i; j++)
437                 {
438                 hash.add(&hash, &zero, 1);
439                 }
440
441             hash.add(&hash, passphrase, pplen);
442             hash.finish(&hash, hashed);
443
444             // if more in hash than is needed by session key, use the leftmost octets
445             memcpy(session_key+(i*SHA_DIGEST_LENGTH), hashed, use);
446             done += use;
447             assert(done<=CAST_KEY_LENGTH);
448             }
449
450         break;
451
452         /* \todo
453     case OPS_S2KS_SALTED:
454     // 8-octet salt value
455         break;
456
457     case OPS_S2KS_ITERATED_AND_SALTED:
458     // 8-octet salt value
459     // 1-octet count
460         break;
461         */
462
463     default:
464         fprintf(stderr,"invalid/unsupported s2k specifier %d\n", key->s2k_specifier);
465         assert(0);
466         }
467
468     /* use this session key to encrypt */
469
470     ops_crypt_any(&crypt,key->algorithm);
471     crypt.set_iv(&crypt, key->iv);
472     crypt.set_key(&crypt, session_key);
473     ops_encrypt_init(&crypt);
474
475     if (debug)
476         {
477         unsigned int i=0;
478         fprintf(stderr,"\nWRITING:\niv=");
479         for (i=0; i<ops_block_size(key->algorithm); i++)
480             {
481             fprintf(stderr, "%02x ", key->iv[i]);
482             }
483         fprintf(stderr,"\n");
484
485         fprintf(stderr,"key=");
486         for (i=0; i<CAST_KEY_LENGTH; i++)
487             {
488             fprintf(stderr, "%02x ", session_key[i]);
489             }
490         fprintf(stderr,"\n");
491
492         ops_print_secret_key(OPS_PTAG_CT_SECRET_KEY,key);
493
494         fprintf(stderr,"turning encryption on...\n");
495         }
496
497     ops_writer_push_encrypt_crypt(info, &crypt);
498
499     switch(key->public_key.algorithm)
500         {
501         //    case OPS_PKA_DSA:
502         //      return ops_write_mpi(key->key.dsa.x,info);
503
504     case OPS_PKA_RSA:
505     case OPS_PKA_RSA_ENCRYPT_ONLY:
506     case OPS_PKA_RSA_SIGN_ONLY:
507
508         if(!ops_write_mpi(key->key.rsa.d,info)
509            || !ops_write_mpi(key->key.rsa.p,info)
510            || !ops_write_mpi(key->key.rsa.q,info)
511            || !ops_write_mpi(key->key.rsa.u,info))
512         {
513         if (debug)
514             { fprintf(stderr,"4 x mpi not written - problem\n"); }
515             return ops_false;
516         }
517
518         break;
519
520         //    case OPS_PKA_ELGAMAL:
521         //      return ops_write_mpi(key->key.elgamal.x,info);
522
523     default:
524         assert(0);
525         break;
526         }
527
528     if(!ops_write(key->checkhash, OPS_CHECKHASH_SIZE, info))
529         return ops_false;
530
531     ops_writer_pop(info);
532    
533     return ops_true;
534  }
535
536
537 ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *key, ops_boolean_t armoured, ops_create_info_t *info)
538     {
539     ops_boolean_t rtn;
540     unsigned int i=0,j=0;
541
542     if (armoured)
543         { ops_writer_push_armoured(info, OPS_PGP_PUBLIC_KEY_BLOCK); }
544
545     // public key
546     rtn=ops_write_struct_public_key(&key->key.skey.public_key,info);
547     if (rtn!=ops_true)
548         return rtn;
549
550     // TODO: revocation signatures go here
551
552     // user ids and corresponding signatures
553     for (i=0; i<key->nuids; i++)
554         {
555         ops_user_id_t* uid=&key->uids[i];
556
557         rtn=ops_write_struct_user_id(uid, info);
558
559         if (!rtn)
560             return rtn;
561
562         // find signature for this packet if it exists
563         for (j=0; j<key->nsigs; j++)
564             {
565             sigpacket_t* sig=&key->sigs[i];
566             if (!strcmp((char *)sig->userid->user_id, (char *)uid->user_id))
567                 {
568                 rtn=ops_write(sig->packet->raw, sig->packet->length, info);
569                 if (!rtn)
570                     return !rtn;
571                 }
572             }
573         }
574
575         // TODO: user attributes and corresponding signatures
576
577         // subkey packets and corresponding signatures and optional revocation
578
579     if (armoured)
580         {
581         writer_info_finalise(&info->errors, &info->winfo);
582         ops_writer_pop(info);
583         }
584
585     return rtn;
586     }
587
588 ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *key, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info)
589     {
590     ops_boolean_t rtn;
591     unsigned int i=0,j=0;
592
593     if (armoured)
594         { ops_writer_push_armoured(info,OPS_PGP_PRIVATE_KEY_BLOCK); }
595
596     // public key
597     rtn=ops_write_struct_secret_key(&key->key.skey,passphrase,pplen,info);
598     if (rtn!=ops_true)
599         return rtn;
600
601     // TODO: revocation signatures go here
602
603     // user ids and corresponding signatures
604     for (i=0; i<key->nuids; i++)
605         {
606         ops_user_id_t* uid=&key->uids[i];
607
608         rtn=ops_write_struct_user_id(uid, info);
609
610         if (!rtn)
611             return rtn;
612
613         // find signature for this packet if it exists
614         for (j=0; j<key->nsigs; j++)
615             {
616             sigpacket_t* sig=&key->sigs[i];
617             if (!strcmp((char *)sig->userid->user_id, (char *)uid->user_id))
618                 {
619                 rtn=ops_write(sig->packet->raw, sig->packet->length, info);
620                 if (!rtn)
621                     return !rtn;
622                 }
623             }
624         }
625
626         // TODO: user attributes and corresponding signatures
627
628         // subkey packets and corresponding signatures and optional revocation
629
630     if (armoured)
631         {
632         writer_info_finalise(&info->errors, &info->winfo);
633         ops_writer_pop(info);
634         }
635
636     return rtn;
637     }
638
639 /**
640  * \ingroup Create
641  *
642  * Writes a Public Key from the information held in "key" and "info"
643  *
644  * \param key
645  * \param info
646  * \return Return value from write_public_key_body() unless call to ops_write_ptag() or ops_write_length() failed before it was called, in which case returns 0
647  * \todo tidy up that return value description!
648  */
649 ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key,
650                                           ops_create_info_t *info)
651     {
652     assert(key->version == 4);
653
654     return ops_write_ptag(OPS_PTAG_CT_PUBLIC_KEY,info)
655         && ops_write_length(1+4+1+public_key_length(key),info)
656         && write_public_key_body(key,info);
657     }
658
659 /**
660  * \ingroup Create
661  *
662  * Writes one RSA public key.
663  *
664  * The parameters for the public key are provided by "time", "n" and "e".
665  *
666  * This function expects "info" to specify a "writer" function to be used, for the
667  * actual output.
668  *
669  * \sa See Detailed Description for usage.
670  *
671  * \param time Creation time
672  * \param n RSA public modulus
673  * \param e RSA public encryption exponent
674  * \param info Writer setup
675  *
676  * \return result from ops_write_struct_public_key()
677  *
678  * \todo get better definition of return values
679  */
680
681 ops_boolean_t ops_write_rsa_public_key(time_t time,const BIGNUM *n,
682                                        const BIGNUM *e,
683                                        ops_create_info_t *info)
684     {
685     ops_public_key_t key;
686
687     ops_fast_create_rsa_public_key(&key,time,DECONST(BIGNUM,n),
688                                    DECONST(BIGNUM,e));
689     return ops_write_struct_public_key(&key,info);
690     }
691
692 /**
693  * \ingroup Create
694  * \param out
695  * \param key
696  * \param make_packet
697  */
698
699 void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key,
700                           ops_boolean_t make_packet)
701     {
702     ops_create_info_t *info;
703
704     info=ops_create_info_new();
705
706     ops_memory_init(out,128);
707     ops_writer_set_memory(info,out);
708
709     write_public_key_body(key,info);
710
711     if(make_packet)
712         ops_memory_make_packet(out,OPS_PTAG_CT_PUBLIC_KEY);
713
714     ops_create_info_delete(info);
715     }
716
717 /**
718  * \ingroup Create
719  *
720  * Create an RSA secret key structure. If a parameter is marked as
721  * [OPTIONAL], then it can be omitted and will be calculated from
722  * other parameters - or, in the case of e, will default to 0x10001.
723  *
724  * Parameters are _not_ copied, so will be freed if the structure is
725  * freed.
726  *
727  * \param key The key structure to be initialised.
728  * \param e The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
729  * \param p The RSA parameter p
730  * \param q The RSA parameter q (q > p)
731  * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
732  * \param n The RSA public parameter n (=p*q) [OPTIONAL]
733  * \param e The RSA public parameter e */
734
735 void ops_fast_create_rsa_secret_key(ops_secret_key_t *key,time_t time,
736                                     BIGNUM *d,BIGNUM *p,BIGNUM *q,BIGNUM *u,
737                                     BIGNUM *n,BIGNUM *e)
738     {
739     ops_fast_create_rsa_public_key(&key->public_key,time,n,e);
740
741     // XXX: calculate optionals
742     key->key.rsa.d=d;
743     key->key.rsa.p=p;
744     key->key.rsa.q=q;
745     key->key.rsa.u=u;
746
747     key->s2k_usage=OPS_S2KU_NONE;
748
749     // XXX: sanity check and add errors...
750     }
751
752 /**
753  * \ingroup Create
754  *
755  * Writes a secret key.
756  *
757  * \param key The secret key
758  * \param info
759  * \return success
760  */
761 ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key,
762                                           const unsigned char* passphrase,
763                                           const size_t pplen,
764                                           ops_create_info_t *info)
765     {
766     int length=0;
767
768     assert(key->public_key.version == 4);
769
770     // Ref: RFC4880 Section 5.5.3
771
772     // public_key, excluding MPIs
773     length += 1+4+1+1;
774
775     // s2k usage
776     length+=1;
777
778     switch (key->s2k_usage)
779         {
780     case OPS_S2KU_NONE:
781         // nothing to add
782         break;
783
784     case OPS_S2KU_ENCRYPTED_AND_HASHED: // 254
785     case OPS_S2KU_ENCRYPTED: // 255
786
787         // Ref: RFC4880 Section 3.7
788         length+=1; // s2k_specifier
789
790         switch(key->s2k_specifier)
791             {
792         case OPS_S2KS_SIMPLE:
793             length+=1; // hash algorithm
794             break;
795
796         case OPS_S2KS_SALTED:
797             length+=1+8; // hash algorithm + salt
798             break;
799
800         case OPS_S2KS_ITERATED_AND_SALTED:
801             length+=1+8+1; // hash algorithm, salt + count
802             break;
803
804         default:
805             assert(0);
806             }
807         break;
808
809     default:
810         assert(0);
811         }
812
813     // IV
814     if (key->s2k_usage != 0)
815         {
816         length += ops_block_size(key->algorithm);
817         }
818
819     // checksum or hash
820     switch (key->s2k_usage)
821         {
822     case 0:
823     case 255:
824         length += 2;
825         break;
826
827     case 254:
828         length += 20;
829         break;
830
831     default:
832         assert(0);
833         }
834
835     // secret key and public key MPIs
836     length += secret_key_length(key);
837
838     return ops_write_ptag(OPS_PTAG_CT_SECRET_KEY,info)
839         //      && ops_write_length(1+4+1+1+secret_key_length(key)+2,info)
840         && ops_write_length(length,info)
841         && write_secret_key_body(key,passphrase,pplen,info);
842     }
843
844 /**
845  * \ingroup Create
846  *
847  * Create a new ops_create_info_t structure.
848  *
849  * \return the new structure.
850  */
851 ops_create_info_t *ops_create_info_new(void)
852     { return ops_mallocz(sizeof(ops_create_info_t)); }
853
854 /* Note that we finalise from the top down, so we don't use writers below
855  * that have already been finalised
856  */
857 static ops_boolean_t writer_info_finalise(ops_error_t **errors,
858                                           ops_writer_info_t *winfo)
859     {
860     ops_boolean_t ret=ops_true;
861
862     if(winfo->finaliser)
863         {
864         ret=winfo->finaliser(errors,winfo);
865         winfo->finaliser=NULL;
866         }
867     if(winfo->next && !writer_info_finalise(errors,winfo->next))
868         {
869         winfo->finaliser=NULL;
870         return ops_false;
871         }
872     return ret;
873     }
874
875 static void writer_info_delete(ops_writer_info_t *winfo)
876     {
877     // we should have finalised before deleting
878     assert(!winfo->finaliser);
879     if(winfo->next)
880         {
881         writer_info_delete(winfo->next);
882         free(winfo->next);
883         winfo->next=NULL;
884         }
885     if(winfo->destroyer)
886         {
887         winfo->destroyer(winfo);
888         winfo->destroyer=NULL;
889         }
890     winfo->writer=NULL;
891     }
892
893 /**
894  * \ingroup Create
895  *
896  * Delete an ops_create_info_t structure. If a writer is active, then
897  * that is also deleted.
898  *
899  * \param info the structure to be deleted.
900  */
901 void ops_create_info_delete(ops_create_info_t *info)
902     {
903     writer_info_delete(&info->winfo);
904     free(info);
905     }
906
907 typedef struct
908     {
909     int fd;
910     } writer_fd_arg_t;
911
912 static ops_boolean_t fd_writer(const unsigned char *src,unsigned length,
913                                ops_error_t **errors,
914                                ops_writer_info_t *winfo)
915     {
916     writer_fd_arg_t *arg=ops_writer_get_arg(winfo);
917     int n=write(arg->fd,src,length);
918
919     if(n == -1)
920         {
921         OPS_SYSTEM_ERROR_1(errors,OPS_E_W_WRITE_FAILED,"write",
922                            "file descriptor %d",arg->fd);
923         return ops_false;
924         }
925
926     if((unsigned)n != length)
927         {
928         OPS_ERROR_1(errors,OPS_E_W_WRITE_TOO_SHORT,
929                     "file descriptor %d",arg->fd);
930         return ops_false;
931         }
932
933     return ops_true;
934     }
935
936 static void fd_destroyer(ops_writer_info_t *winfo)
937     {
938     free(ops_writer_get_arg(winfo));
939     }
940
941 /**
942  * \ingroup Create
943  *
944  * Set the writer in info to be a stock writer that writes to a file
945  * descriptor. If another writer has already been set, then that is
946  * first destroyed.
947  *
948  * \param info The info structure
949  * \param fd The file descriptor
950  *
951  */
952
953 void ops_writer_set_fd(ops_create_info_t *info,int fd)
954     {
955     writer_fd_arg_t *arg=malloc(sizeof *arg);
956
957     arg->fd=fd;
958     ops_writer_set(info,fd_writer,NULL,fd_destroyer,arg);
959     }
960
961 /**
962  * \ingroup Create
963  *
964  * Set a writer in info. There should not be another writer set.
965  *
966  * \param info The info structure
967  * \param writer The writer
968  * \param destroyer The destroyer
969  * \param arg The argument for the writer and destroyer
970  */
971 void ops_writer_set(ops_create_info_t *info,
972                     ops_writer_t *writer,
973                     ops_writer_finaliser_t *finaliser,
974                     ops_writer_destroyer_t *destroyer,
975                     void *arg)
976     {
977     assert(!info->winfo.writer);
978     info->winfo.writer=writer;
979     info->winfo.finaliser=finaliser;
980     info->winfo.destroyer=destroyer;
981     info->winfo.arg=arg;
982     }
983
984 /**
985  * \ingroup Create
986  *
987  * Push a writer in info. There must already be another writer set.
988  *
989  * \param info The info structure
990  * \param writer The writer
991  * \param destroyer The destroyer
992  * \param arg The argument for the writer and destroyer
993  */
994 void ops_writer_push(ops_create_info_t *info,
995                      ops_writer_t *writer,
996                      ops_writer_finaliser_t *finaliser,
997                      ops_writer_destroyer_t *destroyer,
998                      void *arg)
999     {
1000     ops_writer_info_t *copy=ops_mallocz(sizeof *copy);
1001
1002     assert(info->winfo.writer);
1003     *copy=info->winfo;
1004     info->winfo.next=copy;
1005
1006     info->winfo.writer=writer;
1007     info->winfo.finaliser=finaliser;
1008     info->winfo.destroyer=destroyer;
1009     info->winfo.arg=arg;
1010     }
1011
1012 void ops_writer_pop(ops_create_info_t *info)
1013     {
1014     ops_writer_info_t *next;
1015
1016     // Make sure the finaliser has been called.
1017     assert(!info->winfo.finaliser);
1018     // Make sure this is a stacked writer
1019     assert(info->winfo.next);
1020     if(info->winfo.destroyer)
1021         info->winfo.destroyer(&info->winfo);
1022
1023     next=info->winfo.next;
1024     info->winfo=*next;
1025
1026     free(next);
1027     }
1028
1029 /**
1030  * \ingroup Create
1031  *
1032  * Close the writer currently set in info.
1033  *
1034  * \param info The info structure
1035  */
1036 ops_boolean_t ops_writer_close(ops_create_info_t *info)
1037     {
1038     ops_boolean_t ret=writer_info_finalise(&info->errors,&info->winfo);
1039
1040     writer_info_delete(&info->winfo);
1041
1042     return ret;
1043     }
1044
1045 /**
1046  * \ingroup Create
1047  *
1048  * Get the arg supplied to ops_create_info_set_writer().
1049  *
1050  * \param winfo The writer_info structure
1051  * \return The arg
1052  */
1053 void *ops_writer_get_arg(ops_writer_info_t *winfo)
1054     { return winfo->arg; }
1055
1056 /**
1057  * \ingroup Create
1058  *
1059  * Write to the next writer down in the stack.
1060  *
1061  * \param src The data to write.
1062  * \param length The length of src.
1063  * \param flags The writer flags.
1064  * \param errors A place to store errors.
1065  * \param info The writer_info structure.
1066  * \return Success - if ops_false, then errors should contain the error.
1067  */
1068 ops_boolean_t ops_stacked_write(const void *src,unsigned length,
1069                                 ops_error_t **errors,ops_writer_info_t *winfo)
1070     {
1071     return winfo->next->writer(src,length,errors,winfo->next);
1072     }
1073
1074 /**
1075  * \ingroup Create
1076  *
1077  * Free the arg. Many writers just have a malloc()ed lump of storage, this
1078  * function releases it.
1079  *
1080  * \param winfo the info structure.
1081  */
1082 void ops_writer_generic_destroyer(ops_writer_info_t *winfo)
1083     { free(ops_writer_get_arg(winfo)); }
1084
1085 /**
1086  * \ingroup Create
1087  *
1088  * A writer that just writes to the next one down. Useful for when you
1089  * want to insert just a finaliser into the stack.
1090  */
1091 ops_boolean_t ops_writer_passthrough(const unsigned char *src,
1092                                      unsigned length,
1093                                      ops_error_t **errors,
1094                                      ops_writer_info_t *winfo)
1095     { return ops_stacked_write(src,length,errors,winfo); }
1096
1097
1098 ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, unsigned char *cs)
1099     {
1100     unsigned int i=0;
1101     unsigned long checksum=0;
1102
1103     if (!ops_is_sa_supported(session_key->symmetric_algorithm))
1104         return ops_false;
1105
1106     for (i=0; i<ops_key_size(session_key->symmetric_algorithm); i++)
1107         {
1108         checksum+=session_key->key[i];
1109         }
1110     checksum = checksum % 65536;
1111
1112     cs[0]=checksum >> 8;
1113     cs[1]=checksum & 0xFF;
1114
1115     return ops_true;
1116     //    fprintf(stderr,"\nm buf checksum: ");
1117     //    fprintf(stderr," %2x",cs[0]);
1118     //    fprintf(stderr," %2x\n",cs[1]);
1119     }   
1120
1121 static ops_boolean_t create_unencoded_m_buf(ops_pk_session_key_t *session_key, unsigned char *m_buf)
1122     {
1123     int i=0;
1124     //    unsigned long checksum=0;
1125
1126     // m_buf is the buffer which will be encoded in PKCS#1 block
1127     // encoding to form the "m" value used in the
1128     // Public Key Encrypted Session Key Packet
1129     // as defined in RFC Section 5.1 "Public-Key Encrypted Session Key Packet"
1130
1131     m_buf[0]=session_key->symmetric_algorithm;
1132
1133     assert(session_key->symmetric_algorithm==OPS_SA_CAST5);
1134     for (i=0; i<CAST_KEY_LENGTH; i++)
1135         {
1136         m_buf[1+i]=session_key->key[i];
1137         }
1138
1139     return(ops_calc_session_key_checksum(session_key, m_buf+1+CAST_KEY_LENGTH));
1140     }
1141
1142 ops_boolean_t encode_m_buf(const unsigned char *M, size_t mLen,
1143                            const ops_public_key_t *pkey,
1144                            unsigned char* EM
1145 )
1146     {
1147     unsigned int k;
1148     unsigned i;
1149
1150     // implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
1151     
1152     assert(pkey->algorithm == OPS_PKA_RSA);
1153
1154     k=BN_num_bytes(pkey->key.rsa.n);
1155     assert(mLen <= k-11);
1156     if (mLen > k-11)
1157         {
1158         fprintf(stderr,"message too long\n");
1159         return ops_false;
1160         }
1161
1162     // these two bytes defined by RFC
1163     EM[0]=0x00;
1164     EM[1]=0x02;
1165
1166     // add non-zero random bytes of length k - mLen -3
1167     for(i=2 ; i < k-mLen-1 ; ++i)
1168         do
1169             ops_random(EM+i, 1);
1170         while(EM[i] == 0);
1171
1172     assert (i >= 8+2);
1173
1174     EM[i++]=0;
1175
1176     memcpy(EM+i, M, mLen);
1177    
1178
1179     if (debug)
1180         {
1181         unsigned int i=0;
1182         fprintf(stderr,"Encoded Message: \n");
1183         for (i=0; i<mLen; i++)
1184             fprintf(stderr,"%2x ", EM[i]);
1185         fprintf(stderr,"\n");
1186         }
1187
1188     return ops_true;
1189     }
1190
1191 ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key)
1192     {
1193     /*
1194      * Creates a random session key and encrypts it for the given key
1195      *
1196      * Session Key is for use with a SK algo,
1197      * can be any, we're hardcoding CAST5 for now
1198      *
1199      * Encryption used is PK,
1200      * can be any, we're hardcoding RSA for now
1201      */
1202
1203     const ops_public_key_t* pub_key=ops_get_public_key_from_data(key);
1204 #define SZ_UNENCODED_M_BUF CAST_KEY_LENGTH+1+2
1205     unsigned char unencoded_m_buf[SZ_UNENCODED_M_BUF];
1206
1207     const size_t sz_encoded_m_buf=BN_num_bytes(pub_key->key.rsa.n);
1208     unsigned char* encoded_m_buf = ops_mallocz(sz_encoded_m_buf);
1209
1210     ops_pk_session_key_t *session_key=ops_mallocz(sizeof *session_key);
1211
1212     assert(key->type == OPS_PTAG_CT_PUBLIC_KEY);
1213     session_key->version=OPS_PKSK_V3;
1214     memcpy(session_key->key_id, key->key_id, sizeof session_key->key_id);
1215
1216     if (debug)
1217         {
1218         unsigned int i=0;
1219         fprintf(stderr,"Encrypting for RSA key id : ");
1220         for (i=0; i<sizeof session_key->key_id; i++)
1221             fprintf(stderr,"%2x ", key->key_id[i]);
1222         fprintf(stderr,"\n");
1223         }
1224
1225     assert(key->key.pkey.algorithm == OPS_PKA_RSA);
1226     session_key->algorithm=key->key.pkey.algorithm;
1227
1228     // \todo allow user to specify other algorithm
1229     session_key->symmetric_algorithm=OPS_SA_CAST5;
1230     ops_random(session_key->key, CAST_KEY_LENGTH);
1231
1232     if (debug)
1233         {
1234         unsigned int i=0;
1235         fprintf(stderr,"CAST5 session key created (len=%d):\n ", CAST_KEY_LENGTH);
1236         for (i=0; i<CAST_KEY_LENGTH; i++)
1237             fprintf(stderr,"%2x ", session_key->key[i]);
1238         fprintf(stderr,"\n");
1239         }
1240
1241     if (create_unencoded_m_buf(session_key, &unencoded_m_buf[0])==ops_false)
1242         {
1243         free(encoded_m_buf);
1244         return NULL;
1245         }
1246
1247     if (debug)
1248         {
1249         unsigned int i=0;
1250         printf("unencoded m buf:\n");
1251         for (i=0; i<SZ_UNENCODED_M_BUF; i++)
1252             printf("%2x ", unencoded_m_buf[i]);
1253         printf("\n");
1254         }
1255     encode_m_buf(&unencoded_m_buf[0], SZ_UNENCODED_M_BUF, pub_key, &encoded_m_buf[0]);
1256    
1257     // and encrypt it
1258     if(!ops_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pub_key, &session_key->parameters))
1259         {
1260         free (encoded_m_buf);
1261         return NULL;
1262         }
1263
1264     free(encoded_m_buf);
1265     return session_key;
1266     }
1267
1268 ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info,
1269                                        ops_pk_session_key_t *pksk)
1270     {
1271     assert(pksk);
1272     assert(pksk->algorithm == OPS_PKA_RSA);
1273
1274     return ops_write_ptag(OPS_PTAG_CT_PK_SESSION_KEY, info)
1275         && ops_write_length(1 + 8 + 1 + BN_num_bytes(pksk->parameters.rsa.encrypted_m) + 2, info)
1276         && ops_write_scalar(pksk->version, 1, info)
1277         && ops_write(pksk->key_id, 8, info)
1278         && ops_write_scalar(pksk->algorithm, 1, info)
1279         && ops_write_mpi(pksk->parameters.rsa.encrypted_m, info)
1280         //??    && ops_write_scalar(0, 2, info);
1281         ;
1282     }
1283
1284 ops_boolean_t ops_write_mdc(const unsigned char *hashed,
1285                             ops_create_info_t* info)
1286     {
1287     // write it out
1288     return ops_write_ptag(OPS_PTAG_CT_MDC, info)
1289         && ops_write_length(OPS_SHA1_HASH_SIZE,info)
1290         && ops_write(hashed, OPS_SHA1_HASH_SIZE, info);
1291     }
1292
1293 // RENAMED from ops_boolean_t ops_write_literal_data(const unsigned char *data,
1294 ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data,
1295                                      const int maxlen,
1296                                      const ops_literal_data_type_t type,
1297                                      ops_create_info_t *info)
1298     {
1299     // \todo add filename
1300     // \todo add date
1301     // \todo do we need to check text data for <cr><lf> line endings ?
1302     return ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info)
1303         && ops_write_length(1+1+4+maxlen,info)
1304         && ops_write_scalar(type, 1, info)
1305         && ops_write_scalar(0, 1, info)
1306         && ops_write_scalar(0, 4, info)
1307         && ops_write(data, maxlen, info);
1308     }
1309
1310 ops_boolean_t ops_write_literal_data_from_file(const char *filename,
1311                                      const ops_literal_data_type_t type,
1312                                      ops_create_info_t *info)
1313     {
1314     size_t initial_size=1024;
1315     int fd=0;
1316     ops_boolean_t rtn;
1317     unsigned char buf[1024];
1318     ops_memory_t* mem=NULL;
1319     size_t len=0;
1320
1321 #ifdef WIN32
1322     fd=open(filename,O_RDONLY | O_BINARY);
1323 #else
1324     fd=open(filename,O_RDONLY);
1325 #endif
1326     if (fd < 0)
1327         return ops_false;
1328
1329     mem=ops_mallocz(sizeof mem);
1330     ops_memory_init(mem,initial_size);
1331     for (;;)
1332         {
1333         int n=0;
1334         n=read(fd,buf,1024);
1335         if (!n)
1336             break;
1337         ops_memory_add(mem, &buf[0], n);
1338         }
1339     close(fd);   
1340     // \todo add date
1341     // \todo do we need to check text data for <cr><lf> line endings ?
1342     len=ops_memory_get_length(mem);
1343     rtn=ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info)
1344         && ops_write_length(1+1+4+len,info)
1345         && ops_write_scalar(type, 1, info)
1346         && ops_write_scalar(0, 1, info)
1347         && ops_write_scalar(0, 4, info)
1348         && ops_write(ops_memory_get_data(mem), len, info);
1349
1350     ops_memory_free(mem);
1351     return rtn;
1352     }
1353
1354 ops_memory_t* ops_write_buf_from_file(const char *filename)
1355     {
1356     size_t initial_size=1024;
1357     int fd=0;
1358     unsigned char buf[1024];
1359     ops_memory_t* mem=NULL;
1360
1361 #ifdef WIN32
1362     fd=open(filename,O_RDONLY | O_BINARY);
1363 #else
1364     fd=open(filename,O_RDONLY);
1365 #endif
1366     if (fd < 0)
1367         return ops_false;
1368
1369     mem=ops_mallocz(sizeof mem);
1370     ops_memory_init(mem,initial_size);
1371     for (;;)
1372         {
1373         int n=0;
1374         n=read(fd,buf,1024);
1375         if (!n)
1376             break;
1377         ops_memory_add(mem, &buf[0], n);
1378         }
1379     close(fd);   
1380     return mem;
1381     }
1382
1383 int ops_write_file_from_buf(const char *filename, const char* buf, const size_t len)
1384     {
1385     int fd=0;
1386     size_t n=0;
1387
1388 #ifdef WIN32
1389     fd=open(filename,O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600);
1390 #else
1391     fd=open(filename,O_WRONLY | O_CREAT | O_EXCL, 0600);
1392 #endif
1393     if (fd < 0)
1394         {
1395         perror(NULL);
1396         return 0;
1397         }
1398
1399     n=write(fd,buf,len);
1400     if (n!=len)
1401         return 0;
1402
1403     if(!close(fd))
1404         return 1;
1405
1406     return 0;
1407     }
1408
1409 ops_boolean_t ops_write_symmetrically_encrypted_data(const unsigned char *data,
1410                                                      const int len,
1411                                                      ops_create_info_t *info)
1412     {
1413     int done=0;
1414     ops_crypt_t crypt_info;
1415     int encrypted_sz=0;// size of encrypted data
1416     unsigned char *encrypted=(unsigned char *)NULL; // buffer to write encrypted data to
1417     
1418     // \todo assume AES256 for now
1419     ops_crypt_any(&crypt_info, OPS_SA_AES_256);
1420     ops_encrypt_init(&crypt_info);
1421
1422     encrypted_sz=len+crypt_info.blocksize+2;
1423     encrypted=ops_mallocz(encrypted_sz);
1424
1425     done=ops_encrypt_se(&crypt_info, encrypted, data, len);
1426     assert(done==len);
1427     //    printf("len=%d, done: %d\n", len, done);
1428
1429     return ops_write_ptag(OPS_PTAG_CT_SE_DATA, info)
1430         && ops_write_length(1+encrypted_sz,info)
1431         && ops_write(data, len, info);
1432     }
1433
1434 ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey,
1435                                      const ops_hash_algorithm_t hash_alg,
1436                                      const ops_sig_type_t sig_type,
1437                                      ops_create_info_t* info)
1438     {
1439     unsigned char keyid[OPS_KEY_ID_SIZE];
1440     if (debug)
1441         { fprintf(stderr,"calling ops_keyid in write_one_pass_sig: this calls sha1_init\n"); }
1442     ops_keyid(keyid,&skey->public_key);
1443
1444     return ops_write_ptag(OPS_PTAG_CT_ONE_PASS_SIGNATURE, info)
1445         && ops_write_length(1+1+1+1+8+1, info)
1446         && ops_write_scalar (3, 1, info) // version
1447         && ops_write_scalar (sig_type, 1, info)
1448         && ops_write_scalar (hash_alg, 1, info)
1449         && ops_write_scalar (skey->public_key.algorithm,  1, info)
1450         && ops_write(keyid, 8, info)
1451         && ops_write_scalar (1, 1, info);
1452     }
1453
1454
1455
1456 // EOF
1457
Note: See TracBrowser for help on using the browser.