root/openpgpsdk/trunk/src/create.c

Revision 138 (checked in by ben, 8 years ago)

Closer to signing, and parse secret key.

Line 
1 /** \file
2  */
3
4 #include "create.h"
5 #include "util.h"
6 #include "build.h"
7 #include <string.h>
8 #include <assert.h>
9
10 static int base_write(const void *src,unsigned length,
11                        ops_create_options_t *opt)
12     {
13     return opt->writer(src,length,0,opt->arg) == OPS_W_OK;
14     }
15
16 ops_boolean_t ops_write(const void *src,unsigned length,
17                         ops_create_options_t *opt)
18     {
19     return base_write(src,length,opt);
20     }
21
22 ops_boolean_t ops_write_scalar(unsigned n,unsigned length,
23                                ops_create_options_t *opt)
24     {
25     while(length-- > 0)
26         {
27         unsigned char c[1];
28
29         c[0]=n >> (length*8);
30         if(!base_write(c,1,opt))
31             return ops_false;
32         }
33     return ops_true;
34     }
35
36 ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_options_t *opt)
37     {
38     unsigned char buf[8192];
39     int bits=BN_num_bits(bn);
40
41     assert(bits <= 65535);
42     BN_bn2bin(bn,buf);
43     return ops_write_scalar(bits,2,opt)
44         && ops_write(buf,(bits+7)/8,opt);
45     }
46
47 ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_options_t *opt)
48     {
49     unsigned char c[1];
50
51     c[0]=tag|OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT;
52
53     return base_write(c,1,opt);
54     }
55
56 ops_boolean_t ops_write_length(unsigned length,ops_create_options_t *opt)
57     {
58     unsigned char c[2];
59
60     if(length < 192)
61         {
62         c[0]=length;
63         return base_write(c,1,opt);
64         }
65     else if(length < 8384)
66         {
67         c[0]=((length-192) >> 8)+192;
68         c[1]=(length-192)%256;
69         return base_write(c,2,opt);
70         }
71     return ops_write_scalar(0xff,1,opt) && ops_write_scalar(length,4,opt);
72     }
73
74 ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type,
75                                   ops_create_options_t *opt)
76     {
77     return ops_write_length(length,opt)
78         && ops_write_scalar(type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE,1,opt);
79     }
80
81 // XXX: the general idea of _fast_ is that it doesn't copy stuff
82 // the safe (i.e. non _fast_) version will, and so will also need to
83 // be freed.
84 void ops_fast_create_user_id(ops_user_id_t *id,char *user_id)
85     {
86     id->user_id=user_id;;
87     }
88
89 ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id,
90                                        ops_create_options_t *opt)
91     {
92     return ops_write_ptag(OPS_PTAG_CT_USER_ID,opt)
93         && ops_write_length(strlen(id->user_id),opt)
94         && ops_write(id->user_id,strlen(id->user_id),opt);
95     }
96
97 ops_boolean_t ops_write_user_id(const char *user_id,ops_create_options_t *opt)
98     {
99     ops_user_id_t id;
100
101     id.user_id=(char *)user_id;
102     return ops_write_struct_user_id(&id,opt);
103     }
104
105 static unsigned mpi_length(const BIGNUM *bn)
106     {
107     return 2+(BN_num_bits(bn)+7)/8;
108     }
109
110 static unsigned public_key_length(const ops_public_key_t *key)
111     {
112     switch(key->algorithm)
113         {
114     case OPS_PKA_RSA:
115         return mpi_length(key->key.rsa.n)+mpi_length(key->key.rsa.e);
116
117     default:
118         assert(!"unknown key algorithm");
119         }
120     /* not reached */
121     return 0;
122     }
123
124 void ops_fast_create_rsa_public_key(ops_public_key_t *key,time_t time,
125                                     BIGNUM *n,BIGNUM *e)
126     {
127     key->version=4;
128     key->creation_time=time;
129     key->algorithm=OPS_PKA_RSA;
130     key->key.rsa.n=n;
131     key->key.rsa.e=e;
132     }
133
134 // Note that we support v3 keys here because they're needed for
135 // for verification - the writer doesn't allow them, though
136 static int write_public_key_body(const ops_public_key_t *key,
137                                   ops_create_options_t *opt)
138     {
139     if(!(ops_write_scalar(key->version,1,opt)
140          && ops_write_scalar(key->creation_time,4,opt)))
141         return ops_false;
142
143     if(key->version != 4 && !ops_write_scalar(key->days_valid,2,opt))
144         return ops_false;
145
146     if(!ops_write_scalar(key->algorithm,1,opt))
147         return ops_false;
148
149     switch(key->algorithm)
150         {
151     case OPS_PKA_DSA:
152         return ops_write_mpi(key->key.dsa.p,opt)
153             && ops_write_mpi(key->key.dsa.q,opt)
154             && ops_write_mpi(key->key.dsa.g,opt)
155             && ops_write_mpi(key->key.dsa.y,opt);
156
157     case OPS_PKA_RSA:
158     case OPS_PKA_RSA_ENCRYPT_ONLY:
159     case OPS_PKA_RSA_SIGN_ONLY:
160         return ops_write_mpi(key->key.rsa.n,opt)
161             && ops_write_mpi(key->key.rsa.e,opt);
162
163     case OPS_PKA_ELGAMAL:
164         return ops_write_mpi(key->key.elgamal.p,opt)
165             && ops_write_mpi(key->key.elgamal.g,opt)
166             && ops_write_mpi(key->key.elgamal.y,opt);
167
168     default:
169         assert(0);
170         break;
171         }
172
173     /* not reached */
174     return ops_false;
175     }
176
177 ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key,
178                                           ops_create_options_t *opt)
179     {
180     assert(key->version == 4);
181
182     return ops_write_ptag(OPS_PTAG_CT_PUBLIC_KEY,opt)
183         && ops_write_length(1+4+1+public_key_length(key),opt)
184         && write_public_key_body(key,opt);
185     }
186
187 ops_boolean_t ops_write_rsa_public_key(time_t time,const BIGNUM *n,
188                                        const BIGNUM *e,
189                                        ops_create_options_t *opt)
190     {
191     ops_public_key_t key;
192
193     ops_fast_create_rsa_public_key(&key,time,DECONST(BIGNUM,n),
194                                    DECONST(BIGNUM,e));
195     return ops_write_struct_public_key(&key,opt);
196     }
197
198 void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key,
199                           ops_boolean_t make_packet)
200     {
201     ops_create_options_t opt;
202
203     ops_memory_init(out,128);
204     opt.writer=ops_writer_memory;
205     opt.arg=out;
206
207     write_public_key_body(key,&opt);
208
209     if(make_packet)
210         ops_memory_make_packet(out,OPS_PTAG_CT_PUBLIC_KEY);
211     }
Note: See TracBrowser for help on using the browser.