File: | lib/opencdk/write-packet.c |
Location: | line 151, column 3 |
Description: | Value stored to 'rc' is never read |
1 | /* write-packet.c - Write OpenPGP packets |
2 | * Copyright (C) 2001-2003, 2007-2010, 2012 Free Software Foundation, |
3 | * Inc. |
4 | * |
5 | * Author: Timo Schulz |
6 | * |
7 | * This file is part of OpenCDK. |
8 | * |
9 | * The OpenCDK library is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU Lesser General Public License |
11 | * as published by the Free Software Foundation; either version 3 of |
12 | * the License, or (at your option) any later version. |
13 | * |
14 | * This library is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | * Lesser General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public License |
20 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
21 | * |
22 | */ |
23 | #ifdef HAVE_CONFIG_H1 |
24 | #include <config.h> |
25 | #endif |
26 | #include <string.h> |
27 | #include <stdio.h> |
28 | #include <assert.h> |
29 | |
30 | #include "opencdk.h" |
31 | #include "main.h" |
32 | |
33 | |
34 | static int |
35 | stream_write (cdk_stream_t s, const void *buf, size_t buflen) |
36 | { |
37 | int nwritten; |
38 | |
39 | nwritten = cdk_stream_write (s, buf, buflen); |
40 | if (nwritten == EOF(-1)) |
41 | return _cdk_stream_get_errno (s); |
42 | return 0; |
43 | } |
44 | |
45 | |
46 | static int |
47 | stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread) |
48 | { |
49 | int nread; |
50 | |
51 | assert (r_nread)((r_nread) ? (void) (0) : __assert_fail ("r_nread", "write-packet.c" , 51, __PRETTY_FUNCTION__)); |
52 | |
53 | nread = cdk_stream_read (s, buf, buflen); |
54 | if (nread == EOF(-1)) |
55 | return _cdk_stream_get_errno (s); |
56 | *r_nread = nread; |
57 | return 0; |
58 | } |
59 | |
60 | |
61 | static int |
62 | stream_putc (cdk_stream_t s, int c) |
63 | { |
64 | int nwritten = cdk_stream_putc (s, c); |
65 | if (nwritten == EOF(-1)) |
66 | return _cdk_stream_get_errno (s); |
67 | return 0; |
68 | } |
69 | |
70 | |
71 | static int |
72 | write_32 (cdk_stream_t out, u32 u) |
73 | { |
74 | byte buf[4]; |
75 | |
76 | buf[0] = u >> 24; |
77 | buf[1] = u >> 16; |
78 | buf[2] = u >> 8; |
79 | buf[3] = u; |
80 | return stream_write (out, buf, 4); |
81 | } |
82 | |
83 | |
84 | static int |
85 | write_16 (cdk_stream_t out, u16 u) |
86 | { |
87 | byte buf[2]; |
88 | |
89 | buf[0] = u >> 8; |
90 | buf[1] = u; |
91 | return stream_write (out, buf, 2); |
92 | } |
93 | |
94 | |
95 | static size_t |
96 | calc_mpisize (bigint_t mpi[MAX_CDK_PK_PARTS4], size_t ncount) |
97 | { |
98 | size_t size, i; |
99 | |
100 | size = 0; |
101 | for (i = 0; i < ncount; i++) |
102 | size += (_gnutls_mpi_get_nbits (mpi[i])_gnutls_mpi_ops.bigint_get_nbits(mpi[i]) + 7) / 8 + 2; |
103 | return size; |
104 | } |
105 | |
106 | |
107 | static int |
108 | write_mpi (cdk_stream_t out, bigint_t m) |
109 | { |
110 | byte buf[MAX_MPI_BYTES(16384/8) + 2]; |
111 | size_t nbits, nread; |
112 | int err; |
113 | |
114 | if (!out || !m) |
115 | return CDK_Inv_Value; |
116 | nbits = _gnutls_mpi_get_nbits (m)_gnutls_mpi_ops.bigint_get_nbits(m); |
117 | if (nbits > MAX_MPI_BITS16384 || nbits < 1) |
118 | return CDK_MPI_Error; |
119 | |
120 | nread = MAX_MPI_BYTES(16384/8) + 2; |
121 | err = _gnutls_mpi_print_pgp (m, buf, &nread)_gnutls_mpi_ops.bigint_print(m,buf,&nread,GNUTLS_MPI_FORMAT_PGP ); |
122 | if (err < 0) |
123 | return map_gnutls_error_cdk_map_gnutls_error (err); |
124 | return stream_write (out, buf, nread); |
125 | } |
126 | |
127 | |
128 | static cdk_error_t |
129 | write_mpibuf (cdk_stream_t out, bigint_t mpi[MAX_CDK_PK_PARTS4], size_t count) |
130 | { |
131 | size_t i; |
132 | cdk_error_t rc; |
133 | |
134 | for (i = 0; i < count; i++) |
135 | { |
136 | rc = write_mpi (out, mpi[i]); |
137 | if (rc) |
138 | return rc; |
139 | } |
140 | return 0; |
141 | } |
142 | |
143 | |
144 | static cdk_error_t |
145 | pkt_encode_len (cdk_stream_t out, size_t pktlen) |
146 | { |
147 | cdk_error_t rc; |
148 | |
149 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 149, __PRETTY_FUNCTION__)); |
150 | |
151 | rc = 0; |
Value stored to 'rc' is never read | |
152 | if (!pktlen) |
153 | { |
154 | /* Block mode, partial bodies, with 'DEF_BLOCKSIZE' from main.h */ |
155 | rc = stream_putc (out, (0xE0 | DEF_BLOCKBITS13)); |
156 | } |
157 | else if (pktlen < 192) |
158 | rc = stream_putc (out, pktlen); |
159 | else if (pktlen < 8384) |
160 | { |
161 | pktlen -= 192; |
162 | rc = stream_putc (out, (pktlen / 256) + 192); |
163 | if (!rc) |
164 | rc = stream_putc (out, (pktlen % 256)); |
165 | } |
166 | else |
167 | { |
168 | rc = stream_putc (out, 255); |
169 | if (!rc) |
170 | rc = write_32 (out, pktlen); |
171 | } |
172 | |
173 | return rc; |
174 | } |
175 | |
176 | |
177 | static cdk_error_t |
178 | write_head_new (cdk_stream_t out, size_t size, int type) |
179 | { |
180 | cdk_error_t rc; |
181 | |
182 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 182, __PRETTY_FUNCTION__)); |
183 | |
184 | if (type < 0 || type > 63) |
185 | return CDK_Inv_Packet; |
186 | rc = stream_putc (out, (0xC0 | type)); |
187 | if (!rc) |
188 | rc = pkt_encode_len (out, size); |
189 | return rc; |
190 | } |
191 | |
192 | |
193 | static cdk_error_t |
194 | write_head_old (cdk_stream_t out, size_t size, int type) |
195 | { |
196 | cdk_error_t rc; |
197 | int ctb; |
198 | |
199 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 199, __PRETTY_FUNCTION__)); |
200 | |
201 | if (type < 0 || type > 16) |
202 | return CDK_Inv_Packet; |
203 | ctb = 0x80 | (type << 2); |
204 | if (!size) |
205 | ctb |= 3; |
206 | else if (size < 256) |
207 | ; |
208 | else if (size < 65536) |
209 | ctb |= 1; |
210 | else |
211 | ctb |= 2; |
212 | rc = stream_putc (out, ctb); |
213 | if (!size) |
214 | return rc; |
215 | if (!rc) |
216 | { |
217 | if (size < 256) |
218 | rc = stream_putc (out, size); |
219 | else if (size < 65536) |
220 | rc = write_16 (out, size); |
221 | else |
222 | rc = write_32 (out, size); |
223 | } |
224 | |
225 | return rc; |
226 | } |
227 | |
228 | |
229 | /* Write special PGP2 packet header. PGP2 (wrongly) uses two byte header |
230 | length for signatures and keys even if the size is < 256. */ |
231 | static cdk_error_t |
232 | pkt_write_head2 (cdk_stream_t out, size_t size, int type) |
233 | { |
234 | cdk_error_t rc; |
235 | |
236 | rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1); |
237 | if (!rc) |
238 | rc = cdk_stream_putc (out, size >> 8); |
239 | if (!rc) |
240 | rc = cdk_stream_putc (out, size & 0xff); |
241 | return rc; |
242 | } |
243 | |
244 | |
245 | static int |
246 | pkt_write_head (cdk_stream_t out, int old_ctb, size_t size, int type) |
247 | { |
248 | if (old_ctb) |
249 | return write_head_old (out, size, type); |
250 | return write_head_new (out, size, type); |
251 | } |
252 | |
253 | |
254 | static int |
255 | write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb) |
256 | { |
257 | size_t size; |
258 | int rc, nenc; |
259 | |
260 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 260, __PRETTY_FUNCTION__)); |
261 | assert (pke)((pke) ? (void) (0) : __assert_fail ("pke", "write-packet.c", 261, __PRETTY_FUNCTION__)); |
262 | |
263 | if (pke->version < 2 || pke->version > 3) |
264 | return CDK_Inv_Packet; |
265 | if (!KEY_CAN_ENCRYPT (pke->pubkey_algo)((_cdk_pk_algo_usage ((pke->pubkey_algo))) & (CDK_KEY_USG_COMM_ENCR | CDK_KEY_USG_STORAGE_ENCR))) |
266 | return CDK_Inv_Algo; |
267 | |
268 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
269 | _gnutls_write_log ("write_pubkey_enc:\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_pubkey_enc:\n"); } while (0); |
270 | |
271 | nenc = cdk_pk_get_nenc (pke->pubkey_algo); |
272 | size = 10 + calc_mpisize (pke->mpi, nenc); |
273 | rc = pkt_write_head (out, old_ctb, size, CDK_PKT_PUBKEY_ENC); |
274 | if (rc) |
275 | return rc; |
276 | |
277 | rc = stream_putc (out, pke->version); |
278 | if (!rc) |
279 | rc = write_32 (out, pke->keyid[0]); |
280 | if (!rc) |
281 | rc = write_32 (out, pke->keyid[1]); |
282 | if (!rc) |
283 | rc = stream_putc (out, _cdk_pub_algo_to_pgp (pke->pubkey_algo)(pke->pubkey_algo)); |
284 | if (!rc) |
285 | rc = write_mpibuf (out, pke->mpi, nenc); |
286 | return rc; |
287 | } |
288 | |
289 | |
290 | static cdk_error_t |
291 | write_mdc (cdk_stream_t out, cdk_pkt_mdc_t mdc) |
292 | { |
293 | cdk_error_t rc; |
294 | |
295 | assert (mdc)((mdc) ? (void) (0) : __assert_fail ("mdc", "write-packet.c", 295, __PRETTY_FUNCTION__)); |
296 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 296, __PRETTY_FUNCTION__)); |
297 | |
298 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
299 | _gnutls_write_log ("write_mdc:\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_mdc:\n"); } while(0); |
300 | |
301 | /* This packet requires a fixed header encoding */ |
302 | rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */ |
303 | if (!rc) |
304 | rc = stream_putc (out, 0x14); |
305 | if (!rc) |
306 | rc = stream_write (out, mdc->hash, DIM (mdc->hash)(sizeof (mdc->hash)/sizeof ((mdc->hash)[0]))); |
307 | return rc; |
308 | } |
309 | |
310 | |
311 | static size_t |
312 | calc_subpktsize (cdk_subpkt_t s) |
313 | { |
314 | size_t nbytes; |
315 | |
316 | /* In the count mode, no buffer is returned. */ |
317 | _cdk_subpkt_get_array (s, 1, &nbytes); |
318 | return nbytes; |
319 | } |
320 | |
321 | |
322 | static cdk_error_t |
323 | write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig) |
324 | { |
325 | size_t size; |
326 | cdk_error_t rc; |
327 | |
328 | size = 19 + calc_mpisize (sig->mpi, nsig); |
329 | if (is_RSA (sig->pubkey_algo)((sig->pubkey_algo) == CDK_PK_RSA || (sig->pubkey_algo) == CDK_PK_RSA_E || (sig->pubkey_algo) == CDK_PK_RSA_S)) |
330 | rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE); |
331 | else |
332 | rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE); |
333 | if (!rc) |
334 | rc = stream_putc (out, sig->version); |
335 | if (!rc) |
336 | rc = stream_putc (out, 5); |
337 | if (!rc) |
338 | rc = stream_putc (out, sig->sig_class); |
339 | if (!rc) |
340 | rc = write_32 (out, sig->timestamp); |
341 | if (!rc) |
342 | rc = write_32 (out, sig->keyid[0]); |
343 | if (!rc) |
344 | rc = write_32 (out, sig->keyid[1]); |
345 | if (!rc) |
346 | rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo)(sig->pubkey_algo)); |
347 | if (!rc) |
348 | rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo)); |
349 | if (!rc) |
350 | rc = stream_putc (out, sig->digest_start[0]); |
351 | if (!rc) |
352 | rc = stream_putc (out, sig->digest_start[1]); |
353 | if (!rc) |
354 | rc = write_mpibuf (out, sig->mpi, nsig); |
355 | return rc; |
356 | } |
357 | |
358 | |
359 | static cdk_error_t |
360 | write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb) |
361 | { |
362 | byte *buf; |
363 | size_t nbytes, size, nsig; |
364 | cdk_error_t rc; |
365 | |
366 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 366, __PRETTY_FUNCTION__)); |
367 | assert (sig)((sig) ? (void) (0) : __assert_fail ("sig", "write-packet.c", 367, __PRETTY_FUNCTION__)); |
368 | |
369 | if (!KEY_CAN_SIGN (sig->pubkey_algo)((_cdk_pk_algo_usage ((sig->pubkey_algo))) & (CDK_KEY_USG_DATA_SIGN | CDK_KEY_USG_CERT_SIGN))) |
370 | return CDK_Inv_Algo; |
371 | if (sig->version < 2 || sig->version > 4) |
372 | return CDK_Inv_Packet; |
373 | |
374 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
375 | _gnutls_write_log ("write_signature:\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_signature:\n"); } while( 0); |
376 | |
377 | nsig = cdk_pk_get_nsig (sig->pubkey_algo); |
378 | if (!nsig) |
379 | return CDK_Inv_Algo; |
380 | if (sig->version < 4) |
381 | return write_v3_sig (out, sig, nsig); |
382 | |
383 | size = 10 + calc_subpktsize (sig->hashed) |
384 | + calc_subpktsize (sig->unhashed) + calc_mpisize (sig->mpi, nsig); |
385 | rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE); |
386 | if (!rc) |
387 | rc = stream_putc (out, 4); |
388 | if (!rc) |
389 | rc = stream_putc (out, sig->sig_class); |
390 | if (!rc) |
391 | rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo)(sig->pubkey_algo)); |
392 | if (!rc) |
393 | rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo)); |
394 | if (!rc) |
395 | rc = write_16 (out, sig->hashed_size); |
396 | if (!rc) |
397 | { |
398 | buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes); |
399 | if (!buf) |
400 | return CDK_Out_Of_Core; |
401 | rc = stream_write (out, buf, nbytes); |
402 | cdk_freegnutls_free (buf); |
403 | } |
404 | if (!rc) |
405 | rc = write_16 (out, sig->unhashed_size); |
406 | if (!rc) |
407 | { |
408 | buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes); |
409 | if (!buf) |
410 | return CDK_Out_Of_Core; |
411 | rc = stream_write (out, buf, nbytes); |
412 | cdk_freegnutls_free (buf); |
413 | } |
414 | if (!rc) |
415 | rc = stream_putc (out, sig->digest_start[0]); |
416 | if (!rc) |
417 | rc = stream_putc (out, sig->digest_start[1]); |
418 | if (!rc) |
419 | rc = write_mpibuf (out, sig->mpi, nsig); |
420 | return rc; |
421 | } |
422 | |
423 | |
424 | static cdk_error_t |
425 | write_public_key (cdk_stream_t out, cdk_pkt_pubkey_t pk, |
426 | int is_subkey, int old_ctb) |
427 | { |
428 | int pkttype, ndays = 0; |
429 | size_t npkey = 0, size = 6; |
430 | cdk_error_t rc; |
431 | |
432 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 432, __PRETTY_FUNCTION__)); |
433 | assert (pk)((pk) ? (void) (0) : __assert_fail ("pk", "write-packet.c", 433 , __PRETTY_FUNCTION__)); |
434 | |
435 | if (pk->version < 2 || pk->version > 4) |
436 | return CDK_Inv_Packet; |
437 | |
438 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
439 | _gnutls_write_log ("write_public_key: subkey=%d\n", is_subkey)do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_public_key: subkey=%d\n" , is_subkey); } while(0); |
440 | |
441 | pkttype = is_subkey ? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY; |
442 | npkey = cdk_pk_get_npkey (pk->pubkey_algo); |
443 | if (!npkey) |
444 | return CDK_Inv_Algo; |
445 | if (pk->version < 4) |
446 | size += 2; /* expire date */ |
447 | if (is_subkey) |
448 | old_ctb = 0; |
449 | size += calc_mpisize (pk->mpi, npkey); |
450 | if (old_ctb) |
451 | rc = pkt_write_head2 (out, size, pkttype); |
452 | else |
453 | rc = pkt_write_head (out, old_ctb, size, pkttype); |
454 | if (!rc) |
455 | rc = stream_putc (out, pk->version); |
456 | if (!rc) |
457 | rc = write_32 (out, pk->timestamp); |
458 | if (!rc && pk->version < 4) |
459 | { |
460 | if (pk->expiredate) |
461 | ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); |
462 | rc = write_16 (out, ndays); |
463 | } |
464 | if (!rc) |
465 | rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo)(pk->pubkey_algo)); |
466 | if (!rc) |
467 | rc = write_mpibuf (out, pk->mpi, npkey); |
468 | return rc; |
469 | } |
470 | |
471 | |
472 | static int |
473 | calc_s2ksize (cdk_pkt_seckey_t sk) |
474 | { |
475 | size_t nbytes = 0; |
476 | |
477 | if (!sk->is_protected) |
478 | return 0; |
479 | switch (sk->protect.s2k->mode) |
480 | { |
481 | case CDK_S2K_SIMPLE: |
482 | nbytes = 2; |
483 | break; |
484 | case CDK_S2K_SALTED: |
485 | nbytes = 10; |
486 | break; |
487 | case CDK_S2K_ITERSALTED: |
488 | nbytes = 11; |
489 | break; |
490 | } |
491 | nbytes += sk->protect.ivlen; |
492 | nbytes++; /* single cipher byte */ |
493 | return nbytes; |
494 | } |
495 | |
496 | |
497 | static cdk_error_t |
498 | write_secret_key (cdk_stream_t out, cdk_pkt_seckey_t sk, |
499 | int is_subkey, int old_ctb) |
500 | { |
501 | cdk_pkt_pubkey_t pk = NULL((void*)0); |
502 | size_t size = 6, npkey, nskey; |
503 | int pkttype, s2k_mode; |
504 | cdk_error_t rc; |
505 | |
506 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 506, __PRETTY_FUNCTION__)); |
507 | assert (sk)((sk) ? (void) (0) : __assert_fail ("sk", "write-packet.c", 507 , __PRETTY_FUNCTION__)); |
508 | |
509 | if (!sk->pk) |
510 | return CDK_Inv_Value; |
511 | pk = sk->pk; |
512 | if (pk->version < 2 || pk->version > 4) |
513 | return CDK_Inv_Packet; |
514 | |
515 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
516 | _gnutls_write_log ("write_secret_key:\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_secret_key:\n"); } while (0); |
517 | |
518 | npkey = cdk_pk_get_npkey (pk->pubkey_algo); |
519 | nskey = cdk_pk_get_nskey (pk->pubkey_algo); |
520 | if (!npkey || !nskey) |
521 | { |
522 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "write-packet.c",522); } while(0);; |
523 | return CDK_Inv_Algo; |
524 | } |
525 | if (pk->version < 4) |
526 | size += 2; |
527 | /* If the key is unprotected, the 1 extra byte: |
528 | 1 octet - cipher algorithm byte (0x00) |
529 | the other bytes depend on the mode: |
530 | a) simple checksum - 2 octets |
531 | b) sha-1 checksum - 20 octets */ |
532 | size = !sk->is_protected ? size + 1 : size + 1 + calc_s2ksize (sk); |
533 | size += calc_mpisize (pk->mpi, npkey); |
534 | if (sk->version == 3 || !sk->is_protected) |
535 | { |
536 | if (sk->version == 3) |
537 | { |
538 | size += 2; /* force simple checksum */ |
539 | sk->protect.sha1chk = 0; |
540 | } |
541 | else |
542 | size += sk->protect.sha1chk ? 20 : 2; |
543 | size += calc_mpisize (sk->mpi, nskey); |
544 | } |
545 | else /* We do not know anything about the encrypted mpi's so we |
546 | treat the data as opaque. */ |
547 | size += sk->enclen; |
548 | |
549 | pkttype = is_subkey ? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY; |
550 | rc = pkt_write_head (out, old_ctb, size, pkttype); |
551 | if (!rc) |
552 | rc = stream_putc (out, pk->version); |
553 | if (!rc) |
554 | rc = write_32 (out, pk->timestamp); |
555 | if (!rc && pk->version < 4) |
556 | { |
557 | u16 ndays = 0; |
558 | if (pk->expiredate) |
559 | ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); |
560 | rc = write_16 (out, ndays); |
561 | } |
562 | if (!rc) |
563 | rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo)(pk->pubkey_algo)); |
564 | |
565 | if (!rc) |
566 | rc = write_mpibuf (out, pk->mpi, npkey); |
567 | |
568 | if (!rc) |
569 | { |
570 | if (sk->is_protected == 0) |
571 | rc = stream_putc (out, 0x00); |
572 | else |
573 | { |
574 | if (is_RSA (pk->pubkey_algo)((pk->pubkey_algo) == CDK_PK_RSA || (pk->pubkey_algo) == CDK_PK_RSA_E || (pk->pubkey_algo) == CDK_PK_RSA_S) && pk->version < 4) |
575 | rc = stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo)); |
576 | else if (sk->protect.s2k) |
577 | { |
578 | s2k_mode = sk->protect.s2k->mode; |
579 | rc = stream_putc (out, sk->protect.sha1chk ? 0xFE : 0xFF); |
580 | if (!rc) |
581 | rc = |
582 | stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo)); |
583 | if (!rc) |
584 | rc = stream_putc (out, sk->protect.s2k->mode); |
585 | if (!rc) |
586 | rc = stream_putc (out, sk->protect.s2k->hash_algo); |
587 | if (!rc && (s2k_mode == 1 || s2k_mode == 3)) |
588 | { |
589 | rc = stream_write (out, sk->protect.s2k->salt, 8); |
590 | if (!rc && s2k_mode == 3) |
591 | rc = stream_putc (out, sk->protect.s2k->count); |
592 | } |
593 | } |
594 | else |
595 | return CDK_Inv_Value; |
596 | if (!rc) |
597 | rc = stream_write (out, sk->protect.iv, sk->protect.ivlen); |
598 | } |
599 | } |
600 | if (!rc && sk->is_protected && pk->version == 4) |
601 | { |
602 | if (sk->encdata && sk->enclen) |
603 | rc = stream_write (out, sk->encdata, sk->enclen); |
604 | } |
605 | else |
606 | { |
607 | if (!rc) |
608 | rc = write_mpibuf (out, sk->mpi, nskey); |
609 | if (!rc) |
610 | { |
611 | if (!sk->csum) |
612 | sk->csum = _cdk_sk_get_csum (sk); |
613 | rc = write_16 (out, sk->csum); |
614 | } |
615 | } |
616 | |
617 | return rc; |
618 | } |
619 | |
620 | |
621 | static cdk_error_t |
622 | write_compressed (cdk_stream_t out, cdk_pkt_compressed_t cd) |
623 | { |
624 | cdk_error_t rc; |
625 | |
626 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 626, __PRETTY_FUNCTION__)); |
627 | assert (cd)((cd) ? (void) (0) : __assert_fail ("cd", "write-packet.c", 627 , __PRETTY_FUNCTION__)); |
628 | |
629 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
630 | _gnutls_write_log ("packet: write_compressed\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "packet: write_compressed\n"); } while(0); |
631 | |
632 | /* Use an old (RFC1991) header for this packet. */ |
633 | rc = pkt_write_head (out, 1, 0, CDK_PKT_COMPRESSED); |
634 | if (!rc) |
635 | rc = stream_putc (out, cd->algorithm); |
636 | return rc; |
637 | } |
638 | |
639 | |
640 | static cdk_error_t |
641 | write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb) |
642 | { |
643 | byte buf[BUFSIZE8192]; |
644 | size_t size; |
645 | cdk_error_t rc; |
646 | |
647 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 647, __PRETTY_FUNCTION__)); |
648 | assert (pt)((pt) ? (void) (0) : __assert_fail ("pt", "write-packet.c", 648 , __PRETTY_FUNCTION__)); |
649 | |
650 | /* We consider a packet without a body as an invalid packet. |
651 | At least one octet must be present. */ |
652 | if (!pt->len) |
653 | return CDK_Inv_Packet; |
654 | |
655 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
656 | _gnutls_write_log ("write_literal:\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_literal:\n"); } while(0); |
657 | |
658 | size = 6 + pt->namelen + pt->len; |
659 | rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL); |
660 | if (rc) |
661 | return rc; |
662 | |
663 | rc = stream_putc (out, pt->mode); |
664 | if (rc) |
665 | return rc; |
666 | rc = stream_putc (out, pt->namelen); |
667 | if (rc) |
668 | return rc; |
669 | |
670 | if (pt->namelen > 0) |
671 | rc = stream_write (out, pt->name, pt->namelen); |
672 | if (!rc) |
673 | rc = write_32 (out, pt->timestamp); |
674 | if (rc) |
675 | return rc; |
676 | |
677 | while (!cdk_stream_eof (pt->buf) && !rc) |
678 | { |
679 | rc = stream_read (pt->buf, buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])), &size); |
680 | if (!rc) |
681 | rc = stream_write (out, buf, size); |
682 | } |
683 | |
684 | memset (buf, 0, sizeof (buf)); |
685 | return rc; |
686 | } |
687 | |
688 | |
689 | static cdk_error_t |
690 | write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig) |
691 | { |
692 | cdk_error_t rc; |
693 | |
694 | assert (out)((out) ? (void) (0) : __assert_fail ("out", "write-packet.c", 694, __PRETTY_FUNCTION__)); |
695 | assert (sig)((sig) ? (void) (0) : __assert_fail ("sig", "write-packet.c", 695, __PRETTY_FUNCTION__)); |
696 | |
697 | if (sig->version != 3) |
698 | return CDK_Inv_Packet; |
699 | |
700 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
701 | _gnutls_write_log ("write_onepass_sig:\n")do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_onepass_sig:\n"); } while (0); |
702 | |
703 | rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG); |
704 | if (!rc) |
705 | rc = stream_putc (out, sig->version); |
706 | if (!rc) |
707 | rc = stream_putc (out, sig->sig_class); |
708 | if (!rc) |
709 | rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo)); |
710 | if (!rc) |
711 | rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo)(sig->pubkey_algo)); |
712 | if (!rc) |
713 | rc = write_32 (out, sig->keyid[0]); |
714 | if (!rc) |
715 | rc = write_32 (out, sig->keyid[1]); |
716 | if (!rc) |
717 | rc = stream_putc (out, sig->last); |
718 | return rc; |
719 | } |
720 | |
721 | |
722 | static cdk_error_t |
723 | write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb, |
724 | int pkttype) |
725 | { |
726 | cdk_error_t rc; |
727 | |
728 | if (!out || !id) |
729 | return CDK_Inv_Value; |
730 | |
731 | if (pkttype == CDK_PKT_ATTRIBUTE) |
732 | { |
733 | if (!id->attrib_img) |
734 | return CDK_Inv_Value; |
735 | rc = |
736 | pkt_write_head (out, old_ctb, id->attrib_len + 6, CDK_PKT_ATTRIBUTE); |
737 | if (rc) |
738 | return rc; |
739 | /* Write subpacket part. */ |
740 | stream_putc (out, 255); |
741 | write_32 (out, id->attrib_len + 1); |
742 | stream_putc (out, 1); |
743 | rc = stream_write (out, id->attrib_img, id->attrib_len); |
744 | } |
745 | else |
746 | { |
747 | if (!id->name) |
748 | return CDK_Inv_Value; |
749 | rc = pkt_write_head (out, old_ctb, id->len, CDK_PKT_USER_ID); |
750 | if (!rc) |
751 | rc = stream_write (out, id->name, id->len); |
752 | } |
753 | |
754 | return rc; |
755 | } |
756 | |
757 | |
758 | /** |
759 | * cdk_pkt_write: |
760 | * @out: the output stream handle |
761 | * @pkt: the packet itself |
762 | * |
763 | * Write the contents of @pkt into the @out stream. |
764 | * Return 0 on success. |
765 | **/ |
766 | cdk_error_t |
767 | cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt) |
768 | { |
769 | cdk_error_t rc; |
770 | |
771 | if (!out || !pkt) |
772 | return CDK_Inv_Value; |
773 | |
774 | _gnutls_write_log ("write packet pkttype=%d\n", pkt->pkttype)do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write packet pkttype=%d\n", pkt ->pkttype); } while(0); |
775 | switch (pkt->pkttype) |
776 | { |
777 | case CDK_PKT_LITERAL: |
778 | rc = write_literal (out, pkt->pkt.literal, pkt->old_ctb); |
779 | break; |
780 | case CDK_PKT_ONEPASS_SIG: |
781 | rc = write_onepass_sig (out, pkt->pkt.onepass_sig); |
782 | break; |
783 | case CDK_PKT_MDC: |
784 | rc = write_mdc (out, pkt->pkt.mdc); |
785 | break; |
786 | case CDK_PKT_PUBKEY_ENC: |
787 | rc = write_pubkey_enc (out, pkt->pkt.pubkey_enc, pkt->old_ctb); |
788 | break; |
789 | case CDK_PKT_SIGNATURE: |
790 | rc = write_signature (out, pkt->pkt.signature, pkt->old_ctb); |
791 | break; |
792 | case CDK_PKT_PUBLIC_KEY: |
793 | rc = write_public_key (out, pkt->pkt.public_key, 0, pkt->old_ctb); |
794 | break; |
795 | case CDK_PKT_PUBLIC_SUBKEY: |
796 | rc = write_public_key (out, pkt->pkt.public_key, 1, pkt->old_ctb); |
797 | break; |
798 | case CDK_PKT_COMPRESSED: |
799 | rc = write_compressed (out, pkt->pkt.compressed); |
800 | break; |
801 | case CDK_PKT_SECRET_KEY: |
802 | rc = write_secret_key (out, pkt->pkt.secret_key, 0, pkt->old_ctb); |
803 | break; |
804 | case CDK_PKT_SECRET_SUBKEY: |
805 | rc = write_secret_key (out, pkt->pkt.secret_key, 1, pkt->old_ctb); |
806 | break; |
807 | case CDK_PKT_USER_ID: |
808 | case CDK_PKT_ATTRIBUTE: |
809 | rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb, pkt->pkttype); |
810 | break; |
811 | default: |
812 | rc = CDK_Inv_Packet; |
813 | break; |
814 | } |
815 | |
816 | if (DEBUG_PKT(_gnutls_log_level == (CDK_LOG_DEBUG+1))) |
817 | _gnutls_write_log ("write_packet rc=%d pkttype=%d\n", rc, pkt->pkttype)do { if (__builtin_expect((_gnutls_log_level == 7 || _gnutls_log_level > 9), 0)) _gnutls_log( 7, "write_packet rc=%d pkttype=%d\n" , rc, pkt->pkttype); } while(0); |
818 | return rc; |
819 | } |
820 | |
821 | |
822 | cdk_error_t |
823 | _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx) |
824 | { |
825 | cdk_packet_t pkt; |
826 | cdk_error_t rc; |
827 | |
828 | rc = cdk_pkt_new (&pkt); |
829 | if (rc) |
830 | return rc; |
831 | |
832 | switch (pkttype) |
833 | { |
834 | case CDK_PKT_PUBLIC_KEY: |
835 | case CDK_PKT_PUBLIC_SUBKEY: |
836 | pkt->pkt.public_key = pktctx; |
837 | break; |
838 | case CDK_PKT_SIGNATURE: |
839 | pkt->pkt.signature = pktctx; |
840 | break; |
841 | case CDK_PKT_SECRET_KEY: |
842 | case CDK_PKT_SECRET_SUBKEY: |
843 | pkt->pkt.secret_key = pktctx; |
844 | break; |
845 | |
846 | case CDK_PKT_USER_ID: |
847 | pkt->pkt.user_id = pktctx; |
848 | break; |
849 | } |
850 | pkt->pkttype = pkttype; |
851 | rc = cdk_pkt_write (out, pkt); |
852 | cdk_freegnutls_free (pkt); |
853 | return rc; |
854 | } |
855 | |
856 | |
857 | cdk_error_t |
858 | _cdk_pkt_write_fp (FILE * out, cdk_packet_t pkt) |
859 | { |
860 | cdk_stream_t so; |
861 | cdk_error_t rc; |
862 | |
863 | rc = _cdk_stream_fpopen (out, 1, &so); |
864 | if (rc) |
865 | return rc; |
866 | rc = cdk_pkt_write (so, pkt); |
867 | cdk_stream_close (so); |
868 | return rc; |
869 | } |