2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
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
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.
54 #ifdef HAVE_SYS_CDEFS_H
55 #include <sys/cdefs.h>
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 $");
63 #include <sys/types.h>
76 #ifdef HAVE_OPENSSL_RAND_H
77 #include <openssl/rand.h>
84 #include "packet-parse.h"
85 #include "packet-show.h"
86 #include "signature.h"
87 #include "netpgpsdk.h"
88 #include "netpgpdefs.h"
90 #include "readerwriter.h"
92 #include "netpgpdigest.h"
95 #define vsnprintf _vsnprintf
100 __ops_keyring_t
*keyring
;
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
;
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
);
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
,
135 if (keyring
->keyc
> 0) {
136 __ops_add_userid(&keyring
->keys
[keyring
->keyc
- 1],
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],
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
);
155 case OPS_PARSER_ERRCODE
:
156 (void) fprintf(stderr
, "parse error: %s\n",
157 __ops_errcode(content
->errcode
.errcode
));
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
180 __ops_parse_and_accumulate(__ops_keyring_t
*keyring
, __ops_stream_t
*parse
)
182 accumulate_t accumulate
;
183 const int printerrors
= 1;
186 if (parse
->readinfo
.accumulate
) {
187 (void) fprintf(stderr
,
188 "__ops_parse_and_accumulate: already init\n");
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
);
205 * \brief Error Handling
207 #define ERRNAME(code) { code, #code }
209 static __ops_errcode_name_map_t errcode_name_map
[] = {
212 ERRNAME(OPS_E_SYSTEM_ERROR
),
213 ERRNAME(OPS_E_UNIMPLEMENTED
),
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
),
222 ERRNAME(OPS_E_W_WRITE_FAILED
),
223 ERRNAME(OPS_E_W_WRITE_TOO_SHORT
),
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
),
234 ERRNAME(OPS_E_V_BAD_SIGNATURE
),
235 ERRNAME(OPS_E_V_NO_SIGNATURE
),
236 ERRNAME(OPS_E_V_UNKNOWN_SIGNER
),
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
262 * \return error code name or "Unknown"
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 */
273 __ops_new(size_t size
)
277 if ((vp
= calloc(1, size
)) == NULL
) {
278 (void) fprintf(stderr
,
279 "allocation failure for %" PRIsize
"u bytes", size
);
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
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 */
302 unsigned maxbuf
= 128;
306 if ((comment
= calloc(1, maxbuf
+ 1)) == NULL
) {
307 (void) fprintf(stderr
, "calloc comment failure\n");
312 vsnprintf(comment
, maxbuf
+ 1, fmt
, 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");
322 err
->next
= *errstack
;
325 /* fill in the details */
326 err
->errcode
= errcode
;
327 err
->sys_errno
= sys_errno
;
331 err
->comment
= comment
;
336 \brief print this error
337 \param err Error to print
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
,
347 printf("%s, %s\n", __ops_errcode(err
->errcode
), err
->comment
);
353 \brief Print all errors on stack
354 \param errstack Error stack to print
357 __ops_print_errors(__ops_error_t
*errstack
)
361 for (err
= errstack
; err
!= NULL
; err
= err
->next
) {
362 __ops_print_error(err
);
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
374 __ops_has_error(__ops_error_t
*errstack
, __ops_errcode_t errcode
)
378 for (err
= errstack
; err
!= NULL
; err
= err
->next
) {
379 if (err
->errcode
== errcode
) {
388 \brief Frees all errors on stack
389 \param errstack Error stack to free
392 __ops_free_errors(__ops_error_t
*errstack
)
396 while (errstack
!= NULL
) {
397 next
= errstack
->next
;
398 free(errstack
->comment
);
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
415 __ops_fingerprint(__ops_fingerprint_t
*fp
, const __ops_pubkey_t
*key
)
417 if (key
->version
== 2 || key
->version
== 3) {
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");
430 __ops_hash_md5(&md5
);
431 if (!md5
.init(&md5
)) {
432 (void) fprintf(stderr
,
433 "__ops_fingerprint: bad md5 alloc\n");
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");
443 BN_bn2bin(key
->key
.rsa
.n
, bn
);
444 md5
.add(&md5
, bn
, n
);
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");
453 BN_bn2bin(key
->key
.rsa
.e
, bn
);
454 md5
.add(&md5
, bn
, n
);
457 md5
.finish(&md5
, fp
->fingerprint
);
460 __ops_memory_t
*mem
= __ops_memory_new();
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");
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
);
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
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
];
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");
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");
519 BN_bn2bin(key
->key
.rsa
.n
, bn
);
520 (void) memcpy(keyid
, bn
+ n
- idlen
, idlen
);
522 __ops_fingerprint(&finger
, key
);
524 finger
.fingerprint
+ finger
.length
- idlen
,
531 \brief Add to the hash
532 \param hash Hash to add to
534 \param length Length of int in bytes
537 __ops_hash_add_int(__ops_hash_t
*hash
, unsigned n
, unsigned length
)
542 c
= n
>> (length
* 8);
543 hash
->add(hash
, &c
, 1);
549 \brief Setup hash for given hash algorithm
550 \param hash Hash to set up
551 \param alg Hash algorithm to use
554 __ops_hash_any(__ops_hash_t
*hash
, __ops_hash_alg_t alg
)
558 __ops_hash_md5(hash
);
562 __ops_hash_sha1(hash
);
565 case OPS_HASH_SHA256
:
566 __ops_hash_sha256(hash
);
569 case OPS_HASH_SHA384
:
570 __ops_hash_sha384(hash
);
573 case OPS_HASH_SHA512
:
574 __ops_hash_sha512(hash
);
577 case OPS_HASH_SHA224
:
578 __ops_hash_sha224(hash
);
582 (void) fprintf(stderr
, "__ops_hash_any: bad algorithm\n");
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
593 __ops_hash_size(__ops_hash_alg_t alg
)
602 case OPS_HASH_SHA256
:
605 case OPS_HASH_SHA224
:
608 case OPS_HASH_SHA512
:
611 case OPS_HASH_SHA384
:
615 (void) fprintf(stderr
, "__ops_hash_size: bad algorithm\n");
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
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) {
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
;
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
663 __ops_hash(unsigned char *out
, __ops_hash_alg_t alg
, const void *in
,
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
);
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
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
)
697 if (__ops_get_debug_level(__FILE__
)) {
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");
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 */
719 hash
.add(&hash
, preamble
, sz_preamble
);
721 hash
.add(&hash
, plaintext
, sz_plaintext
);
724 hash
.add(&hash
, &c
, 1);
726 c
= OPS_SHA1_HASH_SIZE
;
727 hash
.add(&hash
, &c
, 1);
730 hash
.finish(&hash
, hashed
);
732 if (__ops_get_debug_level(__FILE__
)) {
735 (void) fprintf(stderr
, "\nhashed (len=%d): ",
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
751 __ops_is_hash_alg_supported(const __ops_hash_alg_t
*hash_alg
)
756 case OPS_HASH_SHA256
:
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
777 __ops_memory_init(__ops_memory_t
*mem
, size_t needed
)
783 if (mem
->allocated
< needed
) {
784 if ((temp
= realloc(mem
->buf
, needed
)) == NULL
) {
785 (void) fprintf(stderr
, "__ops_memory_init: bad alloc\n");
788 mem
->allocated
= needed
;
792 if ((mem
->buf
= calloc(1, needed
)) == NULL
) {
793 (void) fprintf(stderr
, "__ops_memory_init: bad alloc\n");
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
807 __ops_memory_pad(__ops_memory_t
*mem
, size_t length
)
811 if (mem
->allocated
< mem
->length
) {
812 (void) fprintf(stderr
, "__ops_memory_pad: bad alloc in\n");
815 if (mem
->allocated
< mem
->length
+ length
) {
816 mem
->allocated
= mem
->allocated
* 2 + length
;
817 temp
= realloc(mem
->buf
, mem
->allocated
);
819 (void) fprintf(stderr
, "__ops_memory_pad: bad alloc\n");
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
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! */
847 __ops_memory_place_int(__ops_memory_t
*mem
, unsigned offset
, unsigned n
,
850 if (mem
->allocated
< offset
+ length
) {
851 (void) fprintf(stderr
,
852 "__ops_memory_place_int: bad alloc\n");
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()
868 __ops_memory_clear(__ops_memory_t
*mem
)
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()
882 __ops_memory_release(__ops_memory_t
*mem
)
885 (void) munmap(mem
->buf
, mem
->length
);
894 __ops_memory_make_packet(__ops_memory_t
*out
, __ops_content_tag_t tag
)
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;
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()
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()
943 __ops_memory_free(__ops_memory_t
*mem
)
945 __ops_memory_release(mem
);
950 \ingroup HighLevel_Memory
951 \brief Get length of data stored in __ops_memory_t struct
952 \return Number of bytes in data
955 __ops_mem_len(const __ops_memory_t
*mem
)
961 \ingroup HighLevel_Memory
962 \brief Get data stored in __ops_memory_t struct
963 \return Pointer to data
966 __ops_mem_data(__ops_memory_t
*mem
)
971 /* read a gile into an __ops_memory_t */
973 __ops_mem_readfile(__ops_memory_t
*mem
, const char *f
)
979 if ((fp
= fopen(f
, "rb")) == NULL
) {
980 (void) fprintf(stderr
,
981 "__ops_mem_readfile: can't open \"%s\"\n", f
);
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");
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
) {
1002 mem
->length
= mem
->allocated
;
1006 return (mem
->allocated
== mem
->length
);
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.
1024 str_from_map_or_null(int type
, __ops_map_t
*map
)
1028 for (row
= map
; row
->string
!= NULL
; row
++) {
1029 if (row
->type
== type
) {
1037 * \ingroup Core_Print
1039 * Searches the given map for the given type.
1040 * Returns a readable string if found, "Unknown" if not.
1044 __ops_str_from_map(int type
, __ops_map_t
*map
)
1048 str
= str_from_map_or_null(type
, map
);
1049 return (str
) ? str
: "Unknown";
1053 hexdump(FILE *fp
, const unsigned char *src
, size_t length
, const char *sep
)
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.
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.
1088 __ops_crypto_finish();
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
);
1100 r
= __ops_stacked_read(dest_
, length
, errors
, readinfo
, cbinfo
);
1104 for (n
= 0; n
< r
; ++n
) {
1105 arg
->sum
= (arg
->sum
+ dest
[n
]) & 0xffff;
1111 sum16_destroyer(__ops_reader_t
*readinfo
)
1113 free(__ops_reader_get_arg(readinfo
));
1117 \ingroup Internal_Readers_Sum16
1118 \param stream Parse settings
1122 __ops_reader_push_sum16(__ops_stream_t
*stream
)
1126 if ((arg
= calloc(1, sizeof(*arg
))) == NULL
) {
1127 (void) fprintf(stderr
, "__ops_reader_push_sum16: bad alloc\n");
1129 __ops_reader_push(stream
, sum16_reader
, sum16_destroyer
, arg
);
1134 \ingroup Internal_Readers_Sum16
1135 \param stream Parse settings
1139 __ops_reader_pop_sum16(__ops_stream_t
*stream
)
1144 arg
= __ops_reader_get_arg(__ops_readinfo(stream
));
1146 __ops_reader_pop(stream
);
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 */
1155 MAX_DEBUG_NAMES
= 32
1159 static char *debugv
[MAX_DEBUG_NAMES
];
1161 /* set the debugging level per filename */
1163 __ops_set_debug_level(const char *f
)
1171 if ((name
= strrchr(f
, '/')) == NULL
) {
1176 for (i
= 0; i
< debugc
&& i
< MAX_DEBUG_NAMES
; i
++) {
1177 if (strcmp(debugv
[i
], name
) == 0) {
1181 if (i
== MAX_DEBUG_NAMES
) {
1184 debugv
[debugc
++] = strdup(name
);
1188 /* get the debugging level per filename */
1190 __ops_get_debug_level(const char *f
)
1195 if ((name
= strrchr(f
, '/')) == NULL
) {
1200 for (i
= 0; i
< debugc
; i
++) {
1201 if (strcmp(debugv
[i
], "all") == 0 ||
1202 strcmp(debugv
[i
], name
) == 0) {
1209 /* return the version for the library */
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
;
1222 /* local version of asprintf so we don't have to play autoconf games */
1224 __ops_asprintf(char **ret
, const char *fmt
, ...)
1227 char buf
[120 * 1024]; /* XXX - "huge" buffer on stack */
1230 va_start(args
, fmt
);
1231 cc
= vsnprintf(buf
, sizeof(buf
), fmt
, args
);
1233 if ((*ret
= calloc(1, (size_t)(cc
+ 1))) == NULL
) {
1237 (void) memcpy(*ret
, buf
, (size_t)cc
);
1243 netpgp_log(const char *fmt
, ...)
1247 char buf
[BUFSIZ
* 2];
1253 cc
= snprintf(buf
, sizeof(buf
), "%.24s: netpgp: ", cp
);
1255 (void) vsnprintf(&buf
[cc
], sizeof(buf
) - (size_t)cc
, fmt
, vp
);
1257 /* do something with message */
1258 /* put into log buffer? */