Sync usage with man page.
[netbsd-mini2440.git] / crypto / external / bsd / netpgp / dist / src / lib / misc.c
blob3b4c92a63c3d052671583cec1d71947d7d69e29f
1 /*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31 * All rights reserved.
32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33 * their moral rights under the UK Copyright Design and Patents Act 1988 to
34 * be recorded as the authors of this copyright work.
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
42 * Unless required by applicable law or agreed to in writing, software
43 * distributed under the License is distributed on an "AS IS" BASIS,
44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
50 /** \file
52 #include "config.h"
54 #ifdef HAVE_SYS_CDEFS_H
55 #include <sys/cdefs.h>
56 #endif
58 #if defined(__NetBSD__)
59 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60 __RCSID("$NetBSD: misc.c,v 1.25 2009/12/05 07:08:18 agc Exp $");
61 #endif
63 #include <sys/types.h>
64 #include <sys/stat.h>
65 #include <sys/mman.h>
67 #include <stdarg.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
76 #ifdef HAVE_OPENSSL_RAND_H
77 #include <openssl/rand.h>
78 #endif
80 #include "errors.h"
81 #include "packet.h"
82 #include "crypto.h"
83 #include "create.h"
84 #include "packet-parse.h"
85 #include "packet-show.h"
86 #include "signature.h"
87 #include "netpgpsdk.h"
88 #include "netpgpdefs.h"
89 #include "memory.h"
90 #include "readerwriter.h"
91 #include "version.h"
92 #include "netpgpdigest.h"
94 #ifdef WIN32
95 #define vsnprintf _vsnprintf
96 #endif
99 typedef struct {
100 __ops_keyring_t *keyring;
101 } accumulate_t;
104 * \ingroup Core_Callbacks
106 static __ops_cb_ret_t
107 accumulate_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
109 const __ops_contents_t *content = &pkt->u;
110 __ops_keyring_t *keyring;
111 accumulate_t *accumulate;
113 accumulate = __ops_callback_arg(cbinfo);
114 keyring = accumulate->keyring;
115 switch (pkt->tag) {
116 case OPS_PTAG_CT_PUBLIC_KEY:
117 case OPS_PTAG_CT_SECRET_KEY:
118 case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
119 if (__ops_get_debug_level(__FILE__)) {
120 (void) fprintf(stderr, "Creating key %u - tag %u\n",
121 keyring->keyc, pkt->tag);
123 if (pkt->tag == OPS_PTAG_CT_PUBLIC_KEY) {
124 __ops_add_to_pubring(keyring, &content->pubkey);
125 } else {
126 __ops_add_to_secring(keyring, &content->seckey);
128 return OPS_KEEP_MEMORY;
129 case OPS_PTAG_CT_USER_ID:
130 if (__ops_get_debug_level(__FILE__)) {
131 (void) fprintf(stderr, "User ID: %s for key %d\n",
132 content->userid.userid,
133 keyring->keyc - 1);
135 if (keyring->keyc > 0) {
136 __ops_add_userid(&keyring->keys[keyring->keyc - 1],
137 &content->userid);
138 return OPS_KEEP_MEMORY;
140 OPS_ERROR(cbinfo->errors, OPS_E_P_NO_USERID, "No userid found");
141 return OPS_KEEP_MEMORY;
143 case OPS_PARSER_PACKET_END:
144 if (keyring->keyc > 0) {
145 __ops_add_subpacket(&keyring->keys[keyring->keyc - 1],
146 &content->packet);
147 return OPS_KEEP_MEMORY;
149 return OPS_RELEASE_MEMORY;
151 case OPS_PARSER_ERROR:
152 (void) fprintf(stderr, "Error: %s\n", content->error.error);
153 return OPS_FINISHED;
155 case OPS_PARSER_ERRCODE:
156 (void) fprintf(stderr, "parse error: %s\n",
157 __ops_errcode(content->errcode.errcode));
158 break;
160 default:
161 break;
164 /* XXX: we now exclude so many things, we should either drop this or */
165 /* do something to pass on copies of the stuff we keep */
166 return __ops_stacked_callback(pkt, cbinfo);
170 * \ingroup Core_Parse
172 * Parse packets from an input stream until EOF or error.
174 * Key data found in the parsed data is added to #keyring.
176 * \param keyring Pointer to an existing keyring
177 * \param parse Options to use when parsing
179 int
180 __ops_parse_and_accumulate(__ops_keyring_t *keyring, __ops_stream_t *parse)
182 accumulate_t accumulate;
183 const int printerrors = 1;
184 int ret;
186 if (parse->readinfo.accumulate) {
187 (void) fprintf(stderr,
188 "__ops_parse_and_accumulate: already init\n");
189 return 0;
192 (void) memset(&accumulate, 0x0, sizeof(accumulate));
194 accumulate.keyring = keyring;
196 __ops_callback_push(parse, accumulate_cb, &accumulate);
197 parse->readinfo.accumulate = 1;
198 ret = __ops_parse(parse, !printerrors);
200 return ret;
204 /** \file
205 * \brief Error Handling
207 #define ERRNAME(code) { code, #code }
209 static __ops_errcode_name_map_t errcode_name_map[] = {
210 ERRNAME(OPS_E_OK),
211 ERRNAME(OPS_E_FAIL),
212 ERRNAME(OPS_E_SYSTEM_ERROR),
213 ERRNAME(OPS_E_UNIMPLEMENTED),
215 ERRNAME(OPS_E_R),
216 ERRNAME(OPS_E_R_READ_FAILED),
217 ERRNAME(OPS_E_R_EARLY_EOF),
218 ERRNAME(OPS_E_R_BAD_FORMAT),
219 ERRNAME(OPS_E_R_UNCONSUMED_DATA),
221 ERRNAME(OPS_E_W),
222 ERRNAME(OPS_E_W_WRITE_FAILED),
223 ERRNAME(OPS_E_W_WRITE_TOO_SHORT),
225 ERRNAME(OPS_E_P),
226 ERRNAME(OPS_E_P_NOT_ENOUGH_DATA),
227 ERRNAME(OPS_E_P_UNKNOWN_TAG),
228 ERRNAME(OPS_E_P_PACKET_CONSUMED),
229 ERRNAME(OPS_E_P_MPI_FORMAT_ERROR),
231 ERRNAME(OPS_E_C),
233 ERRNAME(OPS_E_V),
234 ERRNAME(OPS_E_V_BAD_SIGNATURE),
235 ERRNAME(OPS_E_V_NO_SIGNATURE),
236 ERRNAME(OPS_E_V_UNKNOWN_SIGNER),
238 ERRNAME(OPS_E_ALG),
239 ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
240 ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
241 ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
242 ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG),
244 ERRNAME(OPS_E_PROTO),
245 ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT),
246 ERRNAME(OPS_E_PROTO_UNKNOWN_SS),
247 ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED),
248 ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN),
249 ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN),
250 ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
251 ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN),
252 ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
253 ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM),
255 {0x00, NULL}, /* this is the end-of-array marker */
259 * \ingroup Core_Errors
260 * \brief returns error code name
261 * \param errcode
262 * \return error code name or "Unknown"
264 const char *
265 __ops_errcode(const __ops_errcode_t errcode)
267 return (__ops_str_from_map((int) errcode,
268 (__ops_map_t *) errcode_name_map));
271 /* generic grab new storage function */
272 void *
273 __ops_new(size_t size)
275 void *vp;
277 if ((vp = calloc(1, size)) == NULL) {
278 (void) fprintf(stderr,
279 "allocation failure for %" PRIsize "u bytes", size);
281 return vp;
285 * \ingroup Core_Errors
286 * \brief Pushes the given error on the given errorstack
287 * \param errstack Error stack to use
288 * \param errcode Code of error to push
289 * \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR)
290 * \param file Source filename where error occurred
291 * \param line Line in source file where error occurred
292 * \param fmt Comment
296 void
297 __ops_push_error(__ops_error_t **errstack, __ops_errcode_t errcode,
298 int sys_errno, const char *file, int line, const char *fmt,...)
300 /* first get the varargs and generate the comment */
301 __ops_error_t *err;
302 unsigned maxbuf = 128;
303 va_list args;
304 char *comment;
306 if ((comment = calloc(1, maxbuf + 1)) == NULL) {
307 (void) fprintf(stderr, "calloc comment failure\n");
308 return;
311 va_start(args, fmt);
312 vsnprintf(comment, maxbuf + 1, fmt, args);
313 va_end(args);
315 /* alloc a new error and add it to the top of the stack */
317 if ((err = calloc(1, sizeof(*err))) == NULL) {
318 (void) fprintf(stderr, "calloc comment failure\n");
319 return;
322 err->next = *errstack;
323 *errstack = err;
325 /* fill in the details */
326 err->errcode = errcode;
327 err->sys_errno = sys_errno;
328 err->file = file;
329 err->line = line;
331 err->comment = comment;
335 \ingroup Core_Errors
336 \brief print this error
337 \param err Error to print
339 void
340 __ops_print_error(__ops_error_t *err)
342 printf("%s:%d: ", err->file, err->line);
343 if (err->errcode == OPS_E_SYSTEM_ERROR) {
344 printf("system error %d returned from %s()\n", err->sys_errno,
345 err->comment);
346 } else {
347 printf("%s, %s\n", __ops_errcode(err->errcode), err->comment);
352 \ingroup Core_Errors
353 \brief Print all errors on stack
354 \param errstack Error stack to print
356 void
357 __ops_print_errors(__ops_error_t *errstack)
359 __ops_error_t *err;
361 for (err = errstack; err != NULL; err = err->next) {
362 __ops_print_error(err);
367 \ingroup Core_Errors
368 \brief Return 1 if given error is present anywhere on stack
369 \param errstack Error stack to check
370 \param errcode Error code to look for
371 \return 1 if found; else 0
373 int
374 __ops_has_error(__ops_error_t *errstack, __ops_errcode_t errcode)
376 __ops_error_t *err;
378 for (err = errstack; err != NULL; err = err->next) {
379 if (err->errcode == errcode) {
380 return 1;
383 return 0;
387 \ingroup Core_Errors
388 \brief Frees all errors on stack
389 \param errstack Error stack to free
391 void
392 __ops_free_errors(__ops_error_t *errstack)
394 __ops_error_t *next;
396 while (errstack != NULL) {
397 next = errstack->next;
398 free(errstack->comment);
399 free(errstack);
400 errstack = next;
404 /** \file
408 * \ingroup Core_Keys
409 * \brief Calculate a public key fingerprint.
410 * \param fp Where to put the calculated fingerprint
411 * \param key The key for which the fingerprint is calculated
414 void
415 __ops_fingerprint(__ops_fingerprint_t *fp, const __ops_pubkey_t *key)
417 if (key->version == 2 || key->version == 3) {
418 unsigned char *bn;
419 size_t n;
420 __ops_hash_t md5;
422 if (key->alg != OPS_PKA_RSA &&
423 key->alg != OPS_PKA_RSA_ENCRYPT_ONLY &&
424 key->alg != OPS_PKA_RSA_SIGN_ONLY) {
425 (void) fprintf(stderr,
426 "__ops_fingerprint: bad algorithm\n");
427 return;
430 __ops_hash_md5(&md5);
431 if (!md5.init(&md5)) {
432 (void) fprintf(stderr,
433 "__ops_fingerprint: bad md5 alloc\n");
434 return;
437 n = (size_t) BN_num_bytes(key->key.rsa.n);
438 if ((bn = calloc(1, n)) == NULL) {
439 (void) fprintf(stderr,
440 "__ops_fingerprint: bad bn alloc\n");
441 return;
443 BN_bn2bin(key->key.rsa.n, bn);
444 md5.add(&md5, bn, n);
445 free(bn);
447 n = (size_t) BN_num_bytes(key->key.rsa.e);
448 if ((bn = calloc(1, n)) == NULL) {
449 (void) fprintf(stderr,
450 "__ops_fingerprint: bad bn alloc 2\n");
451 return;
453 BN_bn2bin(key->key.rsa.e, bn);
454 md5.add(&md5, bn, n);
455 free(bn);
457 md5.finish(&md5, fp->fingerprint);
458 fp->length = 16;
459 } else {
460 __ops_memory_t *mem = __ops_memory_new();
461 __ops_hash_t sha1;
462 size_t len;
464 __ops_build_pubkey(mem, key, 0);
466 if (__ops_get_debug_level(__FILE__)) {
467 fprintf(stderr, "-> creating key fingerprint\n");
469 __ops_hash_sha1(&sha1);
470 if (!sha1.init(&sha1)) {
471 (void) fprintf(stderr,
472 "__ops_fingerprint: bad sha1 alloc\n");
473 return;
476 len = __ops_mem_len(mem);
478 __ops_hash_add_int(&sha1, 0x99, 1);
479 __ops_hash_add_int(&sha1, len, 2);
480 sha1.add(&sha1, __ops_mem_data(mem), len);
481 sha1.finish(&sha1, fp->fingerprint);
483 if (__ops_get_debug_level(__FILE__)) {
484 fprintf(stderr, "<- finished making key fingerprint\n");
486 fp->length = OPS_FINGERPRINT_SIZE;
488 __ops_memory_free(mem);
493 * \ingroup Core_Keys
494 * \brief Calculate the Key ID from the public key.
495 * \param keyid Space for the calculated ID to be stored
496 * \param key The key for which the ID is calculated
499 void
500 __ops_keyid(unsigned char *keyid, const size_t idlen, const __ops_pubkey_t *key)
502 __ops_fingerprint_t finger;
504 if (key->version == 2 || key->version == 3) {
505 unsigned char bn[NETPGP_BUFSIZ];
506 unsigned n;
508 n = (unsigned) BN_num_bytes(key->key.rsa.n);
509 if (n > sizeof(bn)) {
510 (void) fprintf(stderr, "__ops_keyid: bad num bytes\n");
511 return;
513 if (key->alg != OPS_PKA_RSA &&
514 key->alg != OPS_PKA_RSA_ENCRYPT_ONLY &&
515 key->alg != OPS_PKA_RSA_SIGN_ONLY) {
516 (void) fprintf(stderr, "__ops_keyid: bad algorithm\n");
517 return;
519 BN_bn2bin(key->key.rsa.n, bn);
520 (void) memcpy(keyid, bn + n - idlen, idlen);
521 } else {
522 __ops_fingerprint(&finger, key);
523 (void) memcpy(keyid,
524 finger.fingerprint + finger.length - idlen,
525 idlen);
530 \ingroup Core_Hashes
531 \brief Add to the hash
532 \param hash Hash to add to
533 \param n Int to add
534 \param length Length of int in bytes
536 void
537 __ops_hash_add_int(__ops_hash_t *hash, unsigned n, unsigned length)
539 while (length--) {
540 unsigned char c;
542 c = n >> (length * 8);
543 hash->add(hash, &c, 1);
548 \ingroup Core_Hashes
549 \brief Setup hash for given hash algorithm
550 \param hash Hash to set up
551 \param alg Hash algorithm to use
553 void
554 __ops_hash_any(__ops_hash_t *hash, __ops_hash_alg_t alg)
556 switch (alg) {
557 case OPS_HASH_MD5:
558 __ops_hash_md5(hash);
559 break;
561 case OPS_HASH_SHA1:
562 __ops_hash_sha1(hash);
563 break;
565 case OPS_HASH_SHA256:
566 __ops_hash_sha256(hash);
567 break;
569 case OPS_HASH_SHA384:
570 __ops_hash_sha384(hash);
571 break;
573 case OPS_HASH_SHA512:
574 __ops_hash_sha512(hash);
575 break;
577 case OPS_HASH_SHA224:
578 __ops_hash_sha224(hash);
579 break;
581 default:
582 (void) fprintf(stderr, "__ops_hash_any: bad algorithm\n");
587 \ingroup Core_Hashes
588 \brief Returns size of hash for given hash algorithm
589 \param alg Hash algorithm to use
590 \return Size of hash algorithm in bytes
592 unsigned
593 __ops_hash_size(__ops_hash_alg_t alg)
595 switch (alg) {
596 case OPS_HASH_MD5:
597 return 16;
599 case OPS_HASH_SHA1:
600 return 20;
602 case OPS_HASH_SHA256:
603 return 32;
605 case OPS_HASH_SHA224:
606 return 28;
608 case OPS_HASH_SHA512:
609 return 64;
611 case OPS_HASH_SHA384:
612 return 48;
614 default:
615 (void) fprintf(stderr, "__ops_hash_size: bad algorithm\n");
618 return 0;
622 \ingroup Core_Hashes
623 \brief Returns hash enum corresponding to given string
624 \param hash Text name of hash algorithm i.e. "SHA1"
625 \returns Corresponding enum i.e. OPS_HASH_SHA1
627 __ops_hash_alg_t
628 __ops_str_to_hash_alg(const char *hash)
630 if (strcasecmp(hash, "SHA1") == 0) {
631 return OPS_HASH_SHA1;
633 if (strcasecmp(hash, "MD5") == 0) {
634 return OPS_HASH_MD5;
636 if (strcasecmp(hash, "SHA256") == 0) {
637 return OPS_HASH_SHA256;
640 if (strcasecmp(hash,"SHA224") == 0) {
641 return OPS_HASH_SHA224;
644 if (strcasecmp(hash, "SHA512") == 0) {
645 return OPS_HASH_SHA512;
647 if (strcasecmp(hash, "SHA384") == 0) {
648 return OPS_HASH_SHA384;
650 return OPS_HASH_UNKNOWN;
654 \ingroup Core_Hashes
655 \brief Hash given data
656 \param out Where to write the hash
657 \param alg Hash algorithm to use
658 \param in Data to hash
659 \param length Length of data
660 \return Size of hash created
662 unsigned
663 __ops_hash(unsigned char *out, __ops_hash_alg_t alg, const void *in,
664 size_t length)
666 __ops_hash_t hash;
668 __ops_hash_any(&hash, alg);
669 if (!hash.init(&hash)) {
670 (void) fprintf(stderr, "__ops_hash: bad alloc\n");
671 /* we'll just continue here - don't want to return a 0 hash */
672 /* XXX - agc - no way to return failure */
674 hash.add(&hash, in, length);
675 return hash.finish(&hash, out);
679 \ingroup Core_Hashes
680 \brief Calculate hash for MDC packet
681 \param preamble Preamble to hash
682 \param sz_preamble Size of preamble
683 \param plaintext Plaintext to hash
684 \param sz_plaintext Size of plaintext
685 \param hashed Resulting hash
687 void
688 __ops_calc_mdc_hash(const unsigned char *preamble,
689 const size_t sz_preamble,
690 const unsigned char *plaintext,
691 const unsigned sz_plaintext,
692 unsigned char *hashed)
694 unsigned char c;
695 __ops_hash_t hash;
697 if (__ops_get_debug_level(__FILE__)) {
698 unsigned i;
700 (void) fprintf(stderr, "__ops_calc_mdc_hash():\n");
701 (void) fprintf(stderr, "\npreamble: ");
702 for (i = 0; i < sz_preamble; i++)
703 (void) fprintf(stderr, " 0x%02x", preamble[i]);
704 (void) fprintf(stderr, "\n");
705 (void) fprintf(stderr, "\nplaintext (len=%u): ", sz_plaintext);
706 for (i = 0; i < sz_plaintext; i++)
707 (void) fprintf(stderr, " 0x%02x", plaintext[i]);
708 (void) fprintf(stderr, "\n");
710 /* init */
711 __ops_hash_any(&hash, OPS_HASH_SHA1);
712 if (!hash.init(&hash)) {
713 (void) fprintf(stderr, "__ops_calc_mdc_hash: bad alloc\n");
714 /* we'll just continue here - it will die anyway */
715 /* agc - XXX - no way to return failure */
718 /* preamble */
719 hash.add(&hash, preamble, sz_preamble);
720 /* plaintext */
721 hash.add(&hash, plaintext, sz_plaintext);
722 /* MDC packet tag */
723 c = MDC_PKT_TAG;
724 hash.add(&hash, &c, 1);
725 /* MDC packet len */
726 c = OPS_SHA1_HASH_SIZE;
727 hash.add(&hash, &c, 1);
729 /* finish */
730 hash.finish(&hash, hashed);
732 if (__ops_get_debug_level(__FILE__)) {
733 unsigned i;
735 (void) fprintf(stderr, "\nhashed (len=%d): ",
736 OPS_SHA1_HASH_SIZE);
737 for (i = 0; i < OPS_SHA1_HASH_SIZE; i++) {
738 (void) fprintf(stderr, " 0x%02x", hashed[i]);
740 (void) fprintf(stderr, "\n");
745 \ingroup HighLevel_Supported
746 \brief Is this Hash Algorithm supported?
747 \param hash_alg Hash Algorithm to check
748 \return 1 if supported; else 0
750 unsigned
751 __ops_is_hash_alg_supported(const __ops_hash_alg_t *hash_alg)
753 switch (*hash_alg) {
754 case OPS_HASH_MD5:
755 case OPS_HASH_SHA1:
756 case OPS_HASH_SHA256:
757 return 1;
759 default:
760 return 0;
764 void
765 __ops_random(void *dest, size_t length)
767 RAND_bytes(dest, (int)length);
771 \ingroup HighLevel_Memory
772 \brief Memory to initialise
773 \param mem memory to initialise
774 \param needed Size to initialise to
776 void
777 __ops_memory_init(__ops_memory_t *mem, size_t needed)
779 unsigned char *temp;
781 mem->length = 0;
782 if (mem->buf) {
783 if (mem->allocated < needed) {
784 if ((temp = realloc(mem->buf, needed)) == NULL) {
785 (void) fprintf(stderr, "__ops_memory_init: bad alloc\n");
786 } else {
787 mem->buf = temp;
788 mem->allocated = needed;
791 } else {
792 if ((mem->buf = calloc(1, needed)) == NULL) {
793 (void) fprintf(stderr, "__ops_memory_init: bad alloc\n");
794 } else {
795 mem->allocated = needed;
801 \ingroup HighLevel_Memory
802 \brief Pad memory to required length
803 \param mem Memory to use
804 \param length New size
806 void
807 __ops_memory_pad(__ops_memory_t *mem, size_t length)
809 unsigned char *temp;
811 if (mem->allocated < mem->length) {
812 (void) fprintf(stderr, "__ops_memory_pad: bad alloc in\n");
813 return;
815 if (mem->allocated < mem->length + length) {
816 mem->allocated = mem->allocated * 2 + length;
817 temp = realloc(mem->buf, mem->allocated);
818 if (temp == NULL) {
819 (void) fprintf(stderr, "__ops_memory_pad: bad alloc\n");
820 } else {
821 mem->buf = temp;
824 if (mem->allocated < mem->length + length) {
825 (void) fprintf(stderr, "__ops_memory_pad: bad alloc out\n");
830 \ingroup HighLevel_Memory
831 \brief Add data to memory
832 \param mem Memory to which to add
833 \param src Data to add
834 \param length Length of data to add
836 void
837 __ops_memory_add(__ops_memory_t *mem, const unsigned char *src, size_t length)
839 __ops_memory_pad(mem, length);
840 (void) memcpy(mem->buf + mem->length, src, length);
841 mem->length += length;
844 /* XXX: this could be refactored via the writer, but an awful lot of */
845 /* hoops to jump through for 2 lines of code! */
846 void
847 __ops_memory_place_int(__ops_memory_t *mem, unsigned offset, unsigned n,
848 size_t length)
850 if (mem->allocated < offset + length) {
851 (void) fprintf(stderr,
852 "__ops_memory_place_int: bad alloc\n");
853 } else {
854 while (length-- > 0) {
855 mem->buf[offset++] = n >> (length * 8);
861 * \ingroup HighLevel_Memory
862 * \brief Retains allocated memory and set length of stored data to zero.
863 * \param mem Memory to clear
864 * \sa __ops_memory_release()
865 * \sa __ops_memory_free()
867 void
868 __ops_memory_clear(__ops_memory_t *mem)
870 mem->length = 0;
874 \ingroup HighLevel_Memory
875 \brief Free memory and associated data
876 \param mem Memory to free
877 \note This does not free mem itself
878 \sa __ops_memory_clear()
879 \sa __ops_memory_free()
881 void
882 __ops_memory_release(__ops_memory_t *mem)
884 if (mem->mmapped) {
885 (void) munmap(mem->buf, mem->length);
886 } else {
887 free(mem->buf);
889 mem->buf = NULL;
890 mem->length = 0;
893 void
894 __ops_memory_make_packet(__ops_memory_t *out, __ops_content_tag_t tag)
896 size_t extra;
898 extra = (out->length < 192) ? 1 : (out->length < 8192 + 192) ? 2 : 5;
899 __ops_memory_pad(out, extra + 1);
900 memmove(out->buf + extra + 1, out->buf, out->length);
902 out->buf[0] = OPS_PTAG_ALWAYS_SET | OPS_PTAG_NEW_FORMAT | tag;
904 if (out->length < 192) {
905 out->buf[1] = out->length;
906 } else if (out->length < 8192 + 192) {
907 out->buf[1] = ((out->length - 192) >> 8) + 192;
908 out->buf[2] = out->length - 192;
909 } else {
910 out->buf[1] = 0xff;
911 out->buf[2] = out->length >> 24;
912 out->buf[3] = out->length >> 16;
913 out->buf[4] = out->length >> 8;
914 out->buf[5] = out->length;
917 out->length += extra + 1;
921 \ingroup HighLevel_Memory
922 \brief Create a new zeroed __ops_memory_t
923 \return Pointer to new __ops_memory_t
924 \note Free using __ops_memory_free() after use.
925 \sa __ops_memory_free()
928 __ops_memory_t *
929 __ops_memory_new(void)
931 return calloc(1, sizeof(__ops_memory_t));
935 \ingroup HighLevel_Memory
936 \brief Free memory ptr and associated memory
937 \param mem Memory to be freed
938 \sa __ops_memory_release()
939 \sa __ops_memory_clear()
942 void
943 __ops_memory_free(__ops_memory_t *mem)
945 __ops_memory_release(mem);
946 free(mem);
950 \ingroup HighLevel_Memory
951 \brief Get length of data stored in __ops_memory_t struct
952 \return Number of bytes in data
954 size_t
955 __ops_mem_len(const __ops_memory_t *mem)
957 return mem->length;
961 \ingroup HighLevel_Memory
962 \brief Get data stored in __ops_memory_t struct
963 \return Pointer to data
965 void *
966 __ops_mem_data(__ops_memory_t *mem)
968 return mem->buf;
971 /* read a gile into an __ops_memory_t */
973 __ops_mem_readfile(__ops_memory_t *mem, const char *f)
975 struct stat st;
976 FILE *fp;
977 int cc;
979 if ((fp = fopen(f, "rb")) == NULL) {
980 (void) fprintf(stderr,
981 "__ops_mem_readfile: can't open \"%s\"\n", f);
982 return 0;
984 (void) fstat(fileno(fp), &st);
985 mem->allocated = (size_t)st.st_size;
986 mem->buf = mmap(NULL, mem->allocated, PROT_READ,
987 MAP_PRIVATE | MAP_FILE, fileno(fp), 0);
988 if (mem->buf == MAP_FAILED) {
989 /* mmap failed for some reason - try to allocate memory */
990 if ((mem->buf = calloc(1, mem->allocated)) == NULL) {
991 (void) fprintf(stderr, "__ops_mem_readfile: calloc\n");
992 (void) fclose(fp);
993 return 0;
995 /* read into contents of mem */
996 for (mem->length = 0 ;
997 (cc = read(fileno(fp), &mem->buf[mem->length],
998 mem->allocated - mem->length)) > 0 ;
999 mem->length += (size_t)cc) {
1001 } else {
1002 mem->length = mem->allocated;
1003 mem->mmapped = 1;
1005 (void) fclose(fp);
1006 return (mem->allocated == mem->length);
1009 typedef struct {
1010 unsigned short sum;
1011 } sum16_t;
1015 * Searches the given map for the given type.
1016 * Returns a human-readable descriptive string if found,
1017 * returns NULL if not found
1019 * It is the responsibility of the calling function to handle the
1020 * error case sensibly (i.e. don't just print out the return string.
1023 static const char *
1024 str_from_map_or_null(int type, __ops_map_t *map)
1026 __ops_map_t *row;
1028 for (row = map; row->string != NULL; row++) {
1029 if (row->type == type) {
1030 return row->string;
1033 return NULL;
1037 * \ingroup Core_Print
1039 * Searches the given map for the given type.
1040 * Returns a readable string if found, "Unknown" if not.
1043 const char *
1044 __ops_str_from_map(int type, __ops_map_t *map)
1046 const char *str;
1048 str = str_from_map_or_null(type, map);
1049 return (str) ? str : "Unknown";
1052 void
1053 hexdump(FILE *fp, const unsigned char *src, size_t length, const char *sep)
1055 unsigned i;
1057 for (i = 0 ; i < length ; i += 2) {
1058 (void) fprintf(fp, "%02x", *src++);
1059 (void) fprintf(fp, "%02x%s", *src++, sep);
1064 * \ingroup HighLevel_Functions
1065 * \brief Initialises OpenPGP::SDK. To be called before any other OPS function.
1067 * Initialises OpenPGP::SDK and the underlying openssl library.
1070 void
1071 __ops_init(void)
1073 __ops_crypto_init();
1077 * \ingroup HighLevel_Functions
1078 * \brief Closes down OpenPGP::SDK.
1080 * Close down OpenPGP:SDK, release any resources under the control of
1081 * the library. No OpenPGP:SDK function other than __ops_init() should
1082 * be called after this function.
1085 void
1086 __ops_finish(void)
1088 __ops_crypto_finish();
1091 static int
1092 sum16_reader(void *dest_, size_t length, __ops_error_t **errors,
1093 __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo)
1095 const unsigned char *dest = dest_;
1096 sum16_t *arg = __ops_reader_get_arg(readinfo);
1097 int r;
1098 int n;
1100 r = __ops_stacked_read(dest_, length, errors, readinfo, cbinfo);
1101 if (r < 0) {
1102 return r;
1104 for (n = 0; n < r; ++n) {
1105 arg->sum = (arg->sum + dest[n]) & 0xffff;
1107 return r;
1110 static void
1111 sum16_destroyer(__ops_reader_t *readinfo)
1113 free(__ops_reader_get_arg(readinfo));
1117 \ingroup Internal_Readers_Sum16
1118 \param stream Parse settings
1121 void
1122 __ops_reader_push_sum16(__ops_stream_t *stream)
1124 sum16_t *arg;
1126 if ((arg = calloc(1, sizeof(*arg))) == NULL) {
1127 (void) fprintf(stderr, "__ops_reader_push_sum16: bad alloc\n");
1128 } else {
1129 __ops_reader_push(stream, sum16_reader, sum16_destroyer, arg);
1134 \ingroup Internal_Readers_Sum16
1135 \param stream Parse settings
1136 \return sum
1138 unsigned short
1139 __ops_reader_pop_sum16(__ops_stream_t *stream)
1141 unsigned short sum;
1142 sum16_t *arg;
1144 arg = __ops_reader_get_arg(__ops_readinfo(stream));
1145 sum = arg->sum;
1146 __ops_reader_pop(stream);
1147 free(arg);
1148 return sum;
1151 /* small useful functions for setting the file-level debugging levels */
1152 /* if the debugv list contains the filename in question, we're debugging it */
1154 enum {
1155 MAX_DEBUG_NAMES = 32
1158 static int debugc;
1159 static char *debugv[MAX_DEBUG_NAMES];
1161 /* set the debugging level per filename */
1163 __ops_set_debug_level(const char *f)
1165 const char *name;
1166 int i;
1168 if (f == NULL) {
1169 f = "all";
1171 if ((name = strrchr(f, '/')) == NULL) {
1172 name = f;
1173 } else {
1174 name += 1;
1176 for (i = 0; i < debugc && i < MAX_DEBUG_NAMES; i++) {
1177 if (strcmp(debugv[i], name) == 0) {
1178 return 1;
1181 if (i == MAX_DEBUG_NAMES) {
1182 return 0;
1184 debugv[debugc++] = strdup(name);
1185 return 1;
1188 /* get the debugging level per filename */
1190 __ops_get_debug_level(const char *f)
1192 const char *name;
1193 int i;
1195 if ((name = strrchr(f, '/')) == NULL) {
1196 name = f;
1197 } else {
1198 name += 1;
1200 for (i = 0; i < debugc; i++) {
1201 if (strcmp(debugv[i], "all") == 0 ||
1202 strcmp(debugv[i], name) == 0) {
1203 return 1;
1206 return 0;
1209 /* return the version for the library */
1210 const char *
1211 __ops_get_info(const char *type)
1213 if (strcmp(type, "version") == 0) {
1214 return NETPGP_VERSION_STRING;
1216 if (strcmp(type, "maintainer") == 0) {
1217 return NETPGP_MAINTAINER;
1219 return "[unknown]";
1222 /* local version of asprintf so we don't have to play autoconf games */
1224 __ops_asprintf(char **ret, const char *fmt, ...)
1226 va_list args;
1227 char buf[120 * 1024]; /* XXX - "huge" buffer on stack */
1228 int cc;
1230 va_start(args, fmt);
1231 cc = vsnprintf(buf, sizeof(buf), fmt, args);
1232 va_end(args);
1233 if ((*ret = calloc(1, (size_t)(cc + 1))) == NULL) {
1234 *ret = NULL;
1235 return -1;
1237 (void) memcpy(*ret, buf, (size_t)cc);
1238 (*ret)[cc] = 0x0;
1239 return cc;
1242 void
1243 netpgp_log(const char *fmt, ...)
1245 va_list vp;
1246 time_t t;
1247 char buf[BUFSIZ * 2];
1248 char *cp;
1249 int cc;
1251 (void) time(&t);
1252 cp = ctime(&t);
1253 cc = snprintf(buf, sizeof(buf), "%.24s: netpgp: ", cp);
1254 va_start(vp, fmt);
1255 (void) vsnprintf(&buf[cc], sizeof(buf) - (size_t)cc, fmt, vp);
1256 va_end(vp);
1257 /* do something with message */
1258 /* put into log buffer? */