1*ebfedea0SLionel Sambuc /*-
2*ebfedea0SLionel Sambuc * Copyright (c) 2009,2010 The NetBSD Foundation, Inc.
3*ebfedea0SLionel Sambuc * All rights reserved.
4*ebfedea0SLionel Sambuc *
5*ebfedea0SLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
6*ebfedea0SLionel Sambuc * by Alistair Crooks (agc@NetBSD.org)
7*ebfedea0SLionel Sambuc *
8*ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc * are met:
11*ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
12*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
13*ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
14*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
15*ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
16*ebfedea0SLionel Sambuc *
17*ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18*ebfedea0SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*ebfedea0SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*ebfedea0SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21*ebfedea0SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*ebfedea0SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*ebfedea0SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*ebfedea0SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*ebfedea0SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*ebfedea0SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*ebfedea0SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
28*ebfedea0SLionel Sambuc */
29*ebfedea0SLionel Sambuc /*
30*ebfedea0SLionel Sambuc * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31*ebfedea0SLionel Sambuc * All rights reserved.
32*ebfedea0SLionel Sambuc * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33*ebfedea0SLionel Sambuc * their moral rights under the UK Copyright Design and Patents Act 1988 to
34*ebfedea0SLionel Sambuc * be recorded as the authors of this copyright work.
35*ebfedea0SLionel Sambuc *
36*ebfedea0SLionel Sambuc * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37*ebfedea0SLionel Sambuc * use this file except in compliance with the License.
38*ebfedea0SLionel Sambuc *
39*ebfedea0SLionel Sambuc * You may obtain a copy of the License at
40*ebfedea0SLionel Sambuc * http://www.apache.org/licenses/LICENSE-2.0
41*ebfedea0SLionel Sambuc *
42*ebfedea0SLionel Sambuc * Unless required by applicable law or agreed to in writing, software
43*ebfedea0SLionel Sambuc * distributed under the License is distributed on an "AS IS" BASIS,
44*ebfedea0SLionel Sambuc * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45*ebfedea0SLionel Sambuc *
46*ebfedea0SLionel Sambuc * See the License for the specific language governing permissions and
47*ebfedea0SLionel Sambuc * limitations under the License.
48*ebfedea0SLionel Sambuc */
49*ebfedea0SLionel Sambuc
50*ebfedea0SLionel Sambuc /** \file
51*ebfedea0SLionel Sambuc */
52*ebfedea0SLionel Sambuc #include "config.h"
53*ebfedea0SLionel Sambuc
54*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_CDEFS_H
55*ebfedea0SLionel Sambuc #include <sys/cdefs.h>
56*ebfedea0SLionel Sambuc #endif
57*ebfedea0SLionel Sambuc
58*ebfedea0SLionel Sambuc #if defined(__NetBSD__)
59*ebfedea0SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*ebfedea0SLionel Sambuc __RCSID("$NetBSD: misc.c,v 1.41 2012/03/05 02:20:18 christos Exp $");
61*ebfedea0SLionel Sambuc #endif
62*ebfedea0SLionel Sambuc
63*ebfedea0SLionel Sambuc #include <sys/types.h>
64*ebfedea0SLionel Sambuc #include <sys/stat.h>
65*ebfedea0SLionel Sambuc #include <sys/mman.h>
66*ebfedea0SLionel Sambuc
67*ebfedea0SLionel Sambuc #include <ctype.h>
68*ebfedea0SLionel Sambuc #include <stdarg.h>
69*ebfedea0SLionel Sambuc #include <stdio.h>
70*ebfedea0SLionel Sambuc #include <stdlib.h>
71*ebfedea0SLionel Sambuc #include <string.h>
72*ebfedea0SLionel Sambuc
73*ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H
74*ebfedea0SLionel Sambuc #include <unistd.h>
75*ebfedea0SLionel Sambuc #endif
76*ebfedea0SLionel Sambuc
77*ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL_RAND_H
78*ebfedea0SLionel Sambuc #include <openssl/rand.h>
79*ebfedea0SLionel Sambuc #endif
80*ebfedea0SLionel Sambuc
81*ebfedea0SLionel Sambuc #include "errors.h"
82*ebfedea0SLionel Sambuc #include "packet.h"
83*ebfedea0SLionel Sambuc #include "crypto.h"
84*ebfedea0SLionel Sambuc #include "create.h"
85*ebfedea0SLionel Sambuc #include "packet-parse.h"
86*ebfedea0SLionel Sambuc #include "packet-show.h"
87*ebfedea0SLionel Sambuc #include "signature.h"
88*ebfedea0SLionel Sambuc #include "netpgpsdk.h"
89*ebfedea0SLionel Sambuc #include "netpgpdefs.h"
90*ebfedea0SLionel Sambuc #include "memory.h"
91*ebfedea0SLionel Sambuc #include "readerwriter.h"
92*ebfedea0SLionel Sambuc #include "version.h"
93*ebfedea0SLionel Sambuc #include "netpgpdigest.h"
94*ebfedea0SLionel Sambuc
95*ebfedea0SLionel Sambuc #ifdef WIN32
96*ebfedea0SLionel Sambuc #define vsnprintf _vsnprintf
97*ebfedea0SLionel Sambuc #endif
98*ebfedea0SLionel Sambuc
99*ebfedea0SLionel Sambuc
100*ebfedea0SLionel Sambuc typedef struct {
101*ebfedea0SLionel Sambuc pgp_keyring_t *keyring;
102*ebfedea0SLionel Sambuc } accumulate_t;
103*ebfedea0SLionel Sambuc
104*ebfedea0SLionel Sambuc /**
105*ebfedea0SLionel Sambuc * \ingroup Core_Callbacks
106*ebfedea0SLionel Sambuc */
107*ebfedea0SLionel Sambuc static pgp_cb_ret_t
accumulate_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)108*ebfedea0SLionel Sambuc accumulate_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
109*ebfedea0SLionel Sambuc {
110*ebfedea0SLionel Sambuc const pgp_contents_t *content = &pkt->u;
111*ebfedea0SLionel Sambuc pgp_keyring_t *keyring;
112*ebfedea0SLionel Sambuc accumulate_t *accumulate;
113*ebfedea0SLionel Sambuc
114*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
115*ebfedea0SLionel Sambuc (void) fprintf(stderr, "accumulate callback: packet tag %u\n", pkt->tag);
116*ebfedea0SLionel Sambuc }
117*ebfedea0SLionel Sambuc accumulate = pgp_callback_arg(cbinfo);
118*ebfedea0SLionel Sambuc keyring = accumulate->keyring;
119*ebfedea0SLionel Sambuc switch (pkt->tag) {
120*ebfedea0SLionel Sambuc case PGP_PTAG_CT_PUBLIC_KEY:
121*ebfedea0SLionel Sambuc case PGP_PTAG_CT_PUBLIC_SUBKEY:
122*ebfedea0SLionel Sambuc pgp_add_to_pubring(keyring, &content->pubkey, pkt->tag);
123*ebfedea0SLionel Sambuc return PGP_KEEP_MEMORY;
124*ebfedea0SLionel Sambuc case PGP_PTAG_CT_SECRET_KEY:
125*ebfedea0SLionel Sambuc case PGP_PTAG_CT_ENCRYPTED_SECRET_KEY:
126*ebfedea0SLionel Sambuc pgp_add_to_secring(keyring, &content->seckey);
127*ebfedea0SLionel Sambuc return PGP_KEEP_MEMORY;
128*ebfedea0SLionel Sambuc case PGP_PTAG_CT_USER_ID:
129*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
130*ebfedea0SLionel Sambuc (void) fprintf(stderr, "User ID: %s for key %d\n",
131*ebfedea0SLionel Sambuc content->userid,
132*ebfedea0SLionel Sambuc keyring->keyc - 1);
133*ebfedea0SLionel Sambuc }
134*ebfedea0SLionel Sambuc if (keyring->keyc == 0) {
135*ebfedea0SLionel Sambuc PGP_ERROR_1(cbinfo->errors, PGP_E_P_NO_USERID, "%s",
136*ebfedea0SLionel Sambuc "No userid found");
137*ebfedea0SLionel Sambuc } else {
138*ebfedea0SLionel Sambuc pgp_add_userid(&keyring->keys[keyring->keyc - 1], content->userid);
139*ebfedea0SLionel Sambuc }
140*ebfedea0SLionel Sambuc return PGP_KEEP_MEMORY;
141*ebfedea0SLionel Sambuc case PGP_PARSER_PACKET_END:
142*ebfedea0SLionel Sambuc if (keyring->keyc > 0) {
143*ebfedea0SLionel Sambuc pgp_add_subpacket(&keyring->keys[keyring->keyc - 1],
144*ebfedea0SLionel Sambuc &content->packet);
145*ebfedea0SLionel Sambuc return PGP_KEEP_MEMORY;
146*ebfedea0SLionel Sambuc }
147*ebfedea0SLionel Sambuc return PGP_RELEASE_MEMORY;
148*ebfedea0SLionel Sambuc case PGP_PARSER_ERROR:
149*ebfedea0SLionel Sambuc (void) fprintf(stderr, "Error: %s\n", content->error);
150*ebfedea0SLionel Sambuc return PGP_FINISHED;
151*ebfedea0SLionel Sambuc case PGP_PARSER_ERRCODE:
152*ebfedea0SLionel Sambuc (void) fprintf(stderr, "parse error: %s\n",
153*ebfedea0SLionel Sambuc pgp_errcode(content->errcode.errcode));
154*ebfedea0SLionel Sambuc break;
155*ebfedea0SLionel Sambuc default:
156*ebfedea0SLionel Sambuc break;
157*ebfedea0SLionel Sambuc }
158*ebfedea0SLionel Sambuc /* XXX: we now exclude so many things, we should either drop this or */
159*ebfedea0SLionel Sambuc /* do something to pass on copies of the stuff we keep */
160*ebfedea0SLionel Sambuc return pgp_stacked_callback(pkt, cbinfo);
161*ebfedea0SLionel Sambuc }
162*ebfedea0SLionel Sambuc
163*ebfedea0SLionel Sambuc /**
164*ebfedea0SLionel Sambuc * \ingroup Core_Parse
165*ebfedea0SLionel Sambuc *
166*ebfedea0SLionel Sambuc * Parse packets from an input stream until EOF or error.
167*ebfedea0SLionel Sambuc *
168*ebfedea0SLionel Sambuc * Key data found in the parsed data is added to #keyring.
169*ebfedea0SLionel Sambuc *
170*ebfedea0SLionel Sambuc * \param keyring Pointer to an existing keyring
171*ebfedea0SLionel Sambuc * \param parse Options to use when parsing
172*ebfedea0SLionel Sambuc */
173*ebfedea0SLionel Sambuc int
pgp_parse_and_accumulate(pgp_keyring_t * keyring,pgp_stream_t * parse)174*ebfedea0SLionel Sambuc pgp_parse_and_accumulate(pgp_keyring_t *keyring, pgp_stream_t *parse)
175*ebfedea0SLionel Sambuc {
176*ebfedea0SLionel Sambuc accumulate_t accumulate;
177*ebfedea0SLionel Sambuc const int printerrors = 1;
178*ebfedea0SLionel Sambuc int ret;
179*ebfedea0SLionel Sambuc
180*ebfedea0SLionel Sambuc if (parse->readinfo.accumulate) {
181*ebfedea0SLionel Sambuc (void) fprintf(stderr,
182*ebfedea0SLionel Sambuc "pgp_parse_and_accumulate: already init\n");
183*ebfedea0SLionel Sambuc return 0;
184*ebfedea0SLionel Sambuc }
185*ebfedea0SLionel Sambuc
186*ebfedea0SLionel Sambuc (void) memset(&accumulate, 0x0, sizeof(accumulate));
187*ebfedea0SLionel Sambuc
188*ebfedea0SLionel Sambuc accumulate.keyring = keyring;
189*ebfedea0SLionel Sambuc
190*ebfedea0SLionel Sambuc pgp_callback_push(parse, accumulate_cb, &accumulate);
191*ebfedea0SLionel Sambuc parse->readinfo.accumulate = 1;
192*ebfedea0SLionel Sambuc ret = pgp_parse(parse, !printerrors);
193*ebfedea0SLionel Sambuc
194*ebfedea0SLionel Sambuc return ret;
195*ebfedea0SLionel Sambuc }
196*ebfedea0SLionel Sambuc
197*ebfedea0SLionel Sambuc
198*ebfedea0SLionel Sambuc /** \file
199*ebfedea0SLionel Sambuc * \brief Error Handling
200*ebfedea0SLionel Sambuc */
201*ebfedea0SLionel Sambuc #define ERRNAME(code) { code, #code }
202*ebfedea0SLionel Sambuc
203*ebfedea0SLionel Sambuc static pgp_errcode_name_map_t errcode_name_map[] = {
204*ebfedea0SLionel Sambuc ERRNAME(PGP_E_OK),
205*ebfedea0SLionel Sambuc ERRNAME(PGP_E_FAIL),
206*ebfedea0SLionel Sambuc ERRNAME(PGP_E_SYSTEM_ERROR),
207*ebfedea0SLionel Sambuc ERRNAME(PGP_E_UNIMPLEMENTED),
208*ebfedea0SLionel Sambuc
209*ebfedea0SLionel Sambuc ERRNAME(PGP_E_R),
210*ebfedea0SLionel Sambuc ERRNAME(PGP_E_R_READ_FAILED),
211*ebfedea0SLionel Sambuc ERRNAME(PGP_E_R_EARLY_EOF),
212*ebfedea0SLionel Sambuc ERRNAME(PGP_E_R_BAD_FORMAT),
213*ebfedea0SLionel Sambuc ERRNAME(PGP_E_R_UNCONSUMED_DATA),
214*ebfedea0SLionel Sambuc
215*ebfedea0SLionel Sambuc ERRNAME(PGP_E_W),
216*ebfedea0SLionel Sambuc ERRNAME(PGP_E_W_WRITE_FAILED),
217*ebfedea0SLionel Sambuc ERRNAME(PGP_E_W_WRITE_TOO_SHORT),
218*ebfedea0SLionel Sambuc
219*ebfedea0SLionel Sambuc ERRNAME(PGP_E_P),
220*ebfedea0SLionel Sambuc ERRNAME(PGP_E_P_NOT_ENOUGH_DATA),
221*ebfedea0SLionel Sambuc ERRNAME(PGP_E_P_UNKNOWN_TAG),
222*ebfedea0SLionel Sambuc ERRNAME(PGP_E_P_PACKET_CONSUMED),
223*ebfedea0SLionel Sambuc ERRNAME(PGP_E_P_MPI_FORMAT_ERROR),
224*ebfedea0SLionel Sambuc
225*ebfedea0SLionel Sambuc ERRNAME(PGP_E_C),
226*ebfedea0SLionel Sambuc
227*ebfedea0SLionel Sambuc ERRNAME(PGP_E_V),
228*ebfedea0SLionel Sambuc ERRNAME(PGP_E_V_BAD_SIGNATURE),
229*ebfedea0SLionel Sambuc ERRNAME(PGP_E_V_NO_SIGNATURE),
230*ebfedea0SLionel Sambuc ERRNAME(PGP_E_V_UNKNOWN_SIGNER),
231*ebfedea0SLionel Sambuc
232*ebfedea0SLionel Sambuc ERRNAME(PGP_E_ALG),
233*ebfedea0SLionel Sambuc ERRNAME(PGP_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
234*ebfedea0SLionel Sambuc ERRNAME(PGP_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
235*ebfedea0SLionel Sambuc ERRNAME(PGP_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
236*ebfedea0SLionel Sambuc ERRNAME(PGP_E_ALG_UNSUPPORTED_HASH_ALG),
237*ebfedea0SLionel Sambuc
238*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO),
239*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_BAD_SYMMETRIC_DECRYPT),
240*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_UNKNOWN_SS),
241*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_CRITICAL_SS_IGNORED),
242*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_BAD_PUBLIC_KEY_VRSN),
243*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_BAD_SIGNATURE_VRSN),
244*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
245*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_BAD_PKSK_VRSN),
246*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
247*ebfedea0SLionel Sambuc ERRNAME(PGP_E_PROTO_BAD_SK_CHECKSUM),
248*ebfedea0SLionel Sambuc
249*ebfedea0SLionel Sambuc {0x00, NULL}, /* this is the end-of-array marker */
250*ebfedea0SLionel Sambuc };
251*ebfedea0SLionel Sambuc
252*ebfedea0SLionel Sambuc /**
253*ebfedea0SLionel Sambuc * \ingroup Core_Errors
254*ebfedea0SLionel Sambuc * \brief returns error code name
255*ebfedea0SLionel Sambuc * \param errcode
256*ebfedea0SLionel Sambuc * \return error code name or "Unknown"
257*ebfedea0SLionel Sambuc */
258*ebfedea0SLionel Sambuc const char *
pgp_errcode(const pgp_errcode_t errcode)259*ebfedea0SLionel Sambuc pgp_errcode(const pgp_errcode_t errcode)
260*ebfedea0SLionel Sambuc {
261*ebfedea0SLionel Sambuc return (pgp_str_from_map((int) errcode,
262*ebfedea0SLionel Sambuc (pgp_map_t *) errcode_name_map));
263*ebfedea0SLionel Sambuc }
264*ebfedea0SLionel Sambuc
265*ebfedea0SLionel Sambuc /* generic grab new storage function */
266*ebfedea0SLionel Sambuc void *
pgp_new(size_t size)267*ebfedea0SLionel Sambuc pgp_new(size_t size)
268*ebfedea0SLionel Sambuc {
269*ebfedea0SLionel Sambuc void *vp;
270*ebfedea0SLionel Sambuc
271*ebfedea0SLionel Sambuc if ((vp = calloc(1, size)) == NULL) {
272*ebfedea0SLionel Sambuc (void) fprintf(stderr,
273*ebfedea0SLionel Sambuc "allocation failure for %" PRIsize "u bytes", size);
274*ebfedea0SLionel Sambuc }
275*ebfedea0SLionel Sambuc return vp;
276*ebfedea0SLionel Sambuc }
277*ebfedea0SLionel Sambuc
278*ebfedea0SLionel Sambuc /**
279*ebfedea0SLionel Sambuc * \ingroup Core_Errors
280*ebfedea0SLionel Sambuc * \brief Pushes the given error on the given errorstack
281*ebfedea0SLionel Sambuc * \param errstack Error stack to use
282*ebfedea0SLionel Sambuc * \param errcode Code of error to push
283*ebfedea0SLionel Sambuc * \param sys_errno System errno (used if errcode=PGP_E_SYSTEM_ERROR)
284*ebfedea0SLionel Sambuc * \param file Source filename where error occurred
285*ebfedea0SLionel Sambuc * \param line Line in source file where error occurred
286*ebfedea0SLionel Sambuc * \param fmt Comment
287*ebfedea0SLionel Sambuc *
288*ebfedea0SLionel Sambuc */
289*ebfedea0SLionel Sambuc
290*ebfedea0SLionel Sambuc void
pgp_push_error(pgp_error_t ** errstack,pgp_errcode_t errcode,int sys_errno,const char * file,int line,const char * fmt,...)291*ebfedea0SLionel Sambuc pgp_push_error(pgp_error_t **errstack, pgp_errcode_t errcode,
292*ebfedea0SLionel Sambuc int sys_errno, const char *file, int line, const char *fmt,...)
293*ebfedea0SLionel Sambuc {
294*ebfedea0SLionel Sambuc /* first get the varargs and generate the comment */
295*ebfedea0SLionel Sambuc pgp_error_t *err;
296*ebfedea0SLionel Sambuc unsigned maxbuf = 128;
297*ebfedea0SLionel Sambuc va_list args;
298*ebfedea0SLionel Sambuc char *comment;
299*ebfedea0SLionel Sambuc
300*ebfedea0SLionel Sambuc if ((comment = calloc(1, maxbuf + 1)) == NULL) {
301*ebfedea0SLionel Sambuc (void) fprintf(stderr, "calloc comment failure\n");
302*ebfedea0SLionel Sambuc return;
303*ebfedea0SLionel Sambuc }
304*ebfedea0SLionel Sambuc
305*ebfedea0SLionel Sambuc va_start(args, fmt);
306*ebfedea0SLionel Sambuc vsnprintf(comment, maxbuf + 1, fmt, args);
307*ebfedea0SLionel Sambuc va_end(args);
308*ebfedea0SLionel Sambuc
309*ebfedea0SLionel Sambuc /* alloc a new error and add it to the top of the stack */
310*ebfedea0SLionel Sambuc
311*ebfedea0SLionel Sambuc if ((err = calloc(1, sizeof(*err))) == NULL) {
312*ebfedea0SLionel Sambuc (void) fprintf(stderr, "calloc comment failure\n");
313*ebfedea0SLionel Sambuc return;
314*ebfedea0SLionel Sambuc }
315*ebfedea0SLionel Sambuc
316*ebfedea0SLionel Sambuc err->next = *errstack;
317*ebfedea0SLionel Sambuc *errstack = err;
318*ebfedea0SLionel Sambuc
319*ebfedea0SLionel Sambuc /* fill in the details */
320*ebfedea0SLionel Sambuc err->errcode = errcode;
321*ebfedea0SLionel Sambuc err->sys_errno = sys_errno;
322*ebfedea0SLionel Sambuc err->file = file;
323*ebfedea0SLionel Sambuc err->line = line;
324*ebfedea0SLionel Sambuc
325*ebfedea0SLionel Sambuc err->comment = comment;
326*ebfedea0SLionel Sambuc }
327*ebfedea0SLionel Sambuc
328*ebfedea0SLionel Sambuc /**
329*ebfedea0SLionel Sambuc \ingroup Core_Errors
330*ebfedea0SLionel Sambuc \brief print this error
331*ebfedea0SLionel Sambuc \param err Error to print
332*ebfedea0SLionel Sambuc */
333*ebfedea0SLionel Sambuc void
pgp_print_error(pgp_error_t * err)334*ebfedea0SLionel Sambuc pgp_print_error(pgp_error_t *err)
335*ebfedea0SLionel Sambuc {
336*ebfedea0SLionel Sambuc printf("%s:%d: ", err->file, err->line);
337*ebfedea0SLionel Sambuc if (err->errcode == PGP_E_SYSTEM_ERROR) {
338*ebfedea0SLionel Sambuc printf("system error %d returned from %s()\n", err->sys_errno,
339*ebfedea0SLionel Sambuc err->comment);
340*ebfedea0SLionel Sambuc } else {
341*ebfedea0SLionel Sambuc printf("%s, %s\n", pgp_errcode(err->errcode), err->comment);
342*ebfedea0SLionel Sambuc }
343*ebfedea0SLionel Sambuc }
344*ebfedea0SLionel Sambuc
345*ebfedea0SLionel Sambuc /**
346*ebfedea0SLionel Sambuc \ingroup Core_Errors
347*ebfedea0SLionel Sambuc \brief Print all errors on stack
348*ebfedea0SLionel Sambuc \param errstack Error stack to print
349*ebfedea0SLionel Sambuc */
350*ebfedea0SLionel Sambuc void
pgp_print_errors(pgp_error_t * errstack)351*ebfedea0SLionel Sambuc pgp_print_errors(pgp_error_t *errstack)
352*ebfedea0SLionel Sambuc {
353*ebfedea0SLionel Sambuc pgp_error_t *err;
354*ebfedea0SLionel Sambuc
355*ebfedea0SLionel Sambuc for (err = errstack; err != NULL; err = err->next) {
356*ebfedea0SLionel Sambuc pgp_print_error(err);
357*ebfedea0SLionel Sambuc }
358*ebfedea0SLionel Sambuc }
359*ebfedea0SLionel Sambuc
360*ebfedea0SLionel Sambuc /**
361*ebfedea0SLionel Sambuc \ingroup Core_Errors
362*ebfedea0SLionel Sambuc \brief Return 1 if given error is present anywhere on stack
363*ebfedea0SLionel Sambuc \param errstack Error stack to check
364*ebfedea0SLionel Sambuc \param errcode Error code to look for
365*ebfedea0SLionel Sambuc \return 1 if found; else 0
366*ebfedea0SLionel Sambuc */
367*ebfedea0SLionel Sambuc int
pgp_has_error(pgp_error_t * errstack,pgp_errcode_t errcode)368*ebfedea0SLionel Sambuc pgp_has_error(pgp_error_t *errstack, pgp_errcode_t errcode)
369*ebfedea0SLionel Sambuc {
370*ebfedea0SLionel Sambuc pgp_error_t *err;
371*ebfedea0SLionel Sambuc
372*ebfedea0SLionel Sambuc for (err = errstack; err != NULL; err = err->next) {
373*ebfedea0SLionel Sambuc if (err->errcode == errcode) {
374*ebfedea0SLionel Sambuc return 1;
375*ebfedea0SLionel Sambuc }
376*ebfedea0SLionel Sambuc }
377*ebfedea0SLionel Sambuc return 0;
378*ebfedea0SLionel Sambuc }
379*ebfedea0SLionel Sambuc
380*ebfedea0SLionel Sambuc /**
381*ebfedea0SLionel Sambuc \ingroup Core_Errors
382*ebfedea0SLionel Sambuc \brief Frees all errors on stack
383*ebfedea0SLionel Sambuc \param errstack Error stack to free
384*ebfedea0SLionel Sambuc */
385*ebfedea0SLionel Sambuc void
pgp_free_errors(pgp_error_t * errstack)386*ebfedea0SLionel Sambuc pgp_free_errors(pgp_error_t *errstack)
387*ebfedea0SLionel Sambuc {
388*ebfedea0SLionel Sambuc pgp_error_t *next;
389*ebfedea0SLionel Sambuc
390*ebfedea0SLionel Sambuc while (errstack != NULL) {
391*ebfedea0SLionel Sambuc next = errstack->next;
392*ebfedea0SLionel Sambuc free(errstack->comment);
393*ebfedea0SLionel Sambuc free(errstack);
394*ebfedea0SLionel Sambuc errstack = next;
395*ebfedea0SLionel Sambuc }
396*ebfedea0SLionel Sambuc }
397*ebfedea0SLionel Sambuc
398*ebfedea0SLionel Sambuc /* hash a 32-bit integer */
399*ebfedea0SLionel Sambuc static int
hash_uint32(pgp_hash_t * hash,uint32_t n)400*ebfedea0SLionel Sambuc hash_uint32(pgp_hash_t *hash, uint32_t n)
401*ebfedea0SLionel Sambuc {
402*ebfedea0SLionel Sambuc uint8_t ibuf[4];
403*ebfedea0SLionel Sambuc
404*ebfedea0SLionel Sambuc ibuf[0] = (uint8_t)(n >> 24) & 0xff;
405*ebfedea0SLionel Sambuc ibuf[1] = (uint8_t)(n >> 16) & 0xff;
406*ebfedea0SLionel Sambuc ibuf[2] = (uint8_t)(n >> 8) & 0xff;
407*ebfedea0SLionel Sambuc ibuf[3] = (uint8_t)n & 0xff;
408*ebfedea0SLionel Sambuc (*hash->add)(hash, (const uint8_t *)(void *)ibuf, (unsigned)sizeof(ibuf));
409*ebfedea0SLionel Sambuc return sizeof(ibuf);
410*ebfedea0SLionel Sambuc }
411*ebfedea0SLionel Sambuc
412*ebfedea0SLionel Sambuc /* hash a string - first length, then string itself */
413*ebfedea0SLionel Sambuc static int
hash_string(pgp_hash_t * hash,const uint8_t * buf,uint32_t len)414*ebfedea0SLionel Sambuc hash_string(pgp_hash_t *hash, const uint8_t *buf, uint32_t len)
415*ebfedea0SLionel Sambuc {
416*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
417*ebfedea0SLionel Sambuc hexdump(stderr, "hash_string", buf, len);
418*ebfedea0SLionel Sambuc }
419*ebfedea0SLionel Sambuc hash_uint32(hash, len);
420*ebfedea0SLionel Sambuc (*hash->add)(hash, buf, len);
421*ebfedea0SLionel Sambuc return (int)(sizeof(len) + len);
422*ebfedea0SLionel Sambuc }
423*ebfedea0SLionel Sambuc
424*ebfedea0SLionel Sambuc /* hash a bignum, possibly padded - first length, then string itself */
425*ebfedea0SLionel Sambuc static int
hash_bignum(pgp_hash_t * hash,BIGNUM * bignum)426*ebfedea0SLionel Sambuc hash_bignum(pgp_hash_t *hash, BIGNUM *bignum)
427*ebfedea0SLionel Sambuc {
428*ebfedea0SLionel Sambuc uint8_t *bn;
429*ebfedea0SLionel Sambuc size_t len;
430*ebfedea0SLionel Sambuc int padbyte;
431*ebfedea0SLionel Sambuc
432*ebfedea0SLionel Sambuc if (BN_is_zero(bignum)) {
433*ebfedea0SLionel Sambuc hash_uint32(hash, 0);
434*ebfedea0SLionel Sambuc return sizeof(len);
435*ebfedea0SLionel Sambuc }
436*ebfedea0SLionel Sambuc if ((len = (size_t) BN_num_bytes(bignum)) < 1) {
437*ebfedea0SLionel Sambuc (void) fprintf(stderr, "hash_bignum: bad size\n");
438*ebfedea0SLionel Sambuc return 0;
439*ebfedea0SLionel Sambuc }
440*ebfedea0SLionel Sambuc if ((bn = calloc(1, len)) == NULL) {
441*ebfedea0SLionel Sambuc (void) fprintf(stderr, "hash_bignum: bad bn alloc\n");
442*ebfedea0SLionel Sambuc return 0;
443*ebfedea0SLionel Sambuc }
444*ebfedea0SLionel Sambuc BN_bn2bin(bignum, bn + 1);
445*ebfedea0SLionel Sambuc bn[0] = 0x0;
446*ebfedea0SLionel Sambuc padbyte = (bn[1] & 0x80) ? 1 : 0;
447*ebfedea0SLionel Sambuc hash_string(hash, bn + 1 - padbyte, (unsigned)(len + padbyte));
448*ebfedea0SLionel Sambuc free(bn);
449*ebfedea0SLionel Sambuc return (int)(sizeof(len) + len + padbyte);
450*ebfedea0SLionel Sambuc }
451*ebfedea0SLionel Sambuc
452*ebfedea0SLionel Sambuc /** \file
453*ebfedea0SLionel Sambuc */
454*ebfedea0SLionel Sambuc
455*ebfedea0SLionel Sambuc /**
456*ebfedea0SLionel Sambuc * \ingroup Core_Keys
457*ebfedea0SLionel Sambuc * \brief Calculate a public key fingerprint.
458*ebfedea0SLionel Sambuc * \param fp Where to put the calculated fingerprint
459*ebfedea0SLionel Sambuc * \param key The key for which the fingerprint is calculated
460*ebfedea0SLionel Sambuc */
461*ebfedea0SLionel Sambuc int
pgp_fingerprint(pgp_fingerprint_t * fp,const pgp_pubkey_t * key,pgp_hash_alg_t hashtype)462*ebfedea0SLionel Sambuc pgp_fingerprint(pgp_fingerprint_t *fp, const pgp_pubkey_t *key, pgp_hash_alg_t hashtype)
463*ebfedea0SLionel Sambuc {
464*ebfedea0SLionel Sambuc pgp_memory_t *mem;
465*ebfedea0SLionel Sambuc pgp_hash_t hash;
466*ebfedea0SLionel Sambuc const char *type;
467*ebfedea0SLionel Sambuc uint32_t len;
468*ebfedea0SLionel Sambuc
469*ebfedea0SLionel Sambuc mem = pgp_memory_new();
470*ebfedea0SLionel Sambuc if (key->version == 2 || key->version == 3) {
471*ebfedea0SLionel Sambuc if (key->alg != PGP_PKA_RSA &&
472*ebfedea0SLionel Sambuc key->alg != PGP_PKA_RSA_ENCRYPT_ONLY &&
473*ebfedea0SLionel Sambuc key->alg != PGP_PKA_RSA_SIGN_ONLY) {
474*ebfedea0SLionel Sambuc (void) fprintf(stderr,
475*ebfedea0SLionel Sambuc "pgp_fingerprint: bad algorithm\n");
476*ebfedea0SLionel Sambuc return 0;
477*ebfedea0SLionel Sambuc }
478*ebfedea0SLionel Sambuc pgp_hash_md5(&hash);
479*ebfedea0SLionel Sambuc if (!hash.init(&hash)) {
480*ebfedea0SLionel Sambuc (void) fprintf(stderr,
481*ebfedea0SLionel Sambuc "pgp_fingerprint: bad md5 alloc\n");
482*ebfedea0SLionel Sambuc return 0;
483*ebfedea0SLionel Sambuc }
484*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.rsa.n);
485*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.rsa.e);
486*ebfedea0SLionel Sambuc fp->length = hash.finish(&hash, fp->fingerprint);
487*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
488*ebfedea0SLionel Sambuc hexdump(stderr, "v2/v3 fingerprint", fp->fingerprint, fp->length);
489*ebfedea0SLionel Sambuc }
490*ebfedea0SLionel Sambuc } else if (hashtype == PGP_HASH_MD5) {
491*ebfedea0SLionel Sambuc pgp_hash_md5(&hash);
492*ebfedea0SLionel Sambuc if (!hash.init(&hash)) {
493*ebfedea0SLionel Sambuc (void) fprintf(stderr,
494*ebfedea0SLionel Sambuc "pgp_fingerprint: bad md5 alloc\n");
495*ebfedea0SLionel Sambuc return 0;
496*ebfedea0SLionel Sambuc }
497*ebfedea0SLionel Sambuc type = (key->alg == PGP_PKA_RSA) ? "ssh-rsa" : "ssh-dss";
498*ebfedea0SLionel Sambuc hash_string(&hash, (const uint8_t *)(const void *)type, (unsigned)strlen(type));
499*ebfedea0SLionel Sambuc switch(key->alg) {
500*ebfedea0SLionel Sambuc case PGP_PKA_RSA:
501*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.rsa.e);
502*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.rsa.n);
503*ebfedea0SLionel Sambuc break;
504*ebfedea0SLionel Sambuc case PGP_PKA_DSA:
505*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.dsa.p);
506*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.dsa.q);
507*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.dsa.g);
508*ebfedea0SLionel Sambuc hash_bignum(&hash, key->key.dsa.y);
509*ebfedea0SLionel Sambuc break;
510*ebfedea0SLionel Sambuc default:
511*ebfedea0SLionel Sambuc break;
512*ebfedea0SLionel Sambuc }
513*ebfedea0SLionel Sambuc fp->length = hash.finish(&hash, fp->fingerprint);
514*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
515*ebfedea0SLionel Sambuc hexdump(stderr, "md5 fingerprint", fp->fingerprint, fp->length);
516*ebfedea0SLionel Sambuc }
517*ebfedea0SLionel Sambuc } else {
518*ebfedea0SLionel Sambuc pgp_build_pubkey(mem, key, 0);
519*ebfedea0SLionel Sambuc pgp_hash_sha1(&hash);
520*ebfedea0SLionel Sambuc if (!hash.init(&hash)) {
521*ebfedea0SLionel Sambuc (void) fprintf(stderr,
522*ebfedea0SLionel Sambuc "pgp_fingerprint: bad sha1 alloc\n");
523*ebfedea0SLionel Sambuc return 0;
524*ebfedea0SLionel Sambuc }
525*ebfedea0SLionel Sambuc len = (unsigned)pgp_mem_len(mem);
526*ebfedea0SLionel Sambuc pgp_hash_add_int(&hash, 0x99, 1);
527*ebfedea0SLionel Sambuc pgp_hash_add_int(&hash, len, 2);
528*ebfedea0SLionel Sambuc hash.add(&hash, pgp_mem_data(mem), len);
529*ebfedea0SLionel Sambuc fp->length = hash.finish(&hash, fp->fingerprint);
530*ebfedea0SLionel Sambuc pgp_memory_free(mem);
531*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
532*ebfedea0SLionel Sambuc hexdump(stderr, "sha1 fingerprint", fp->fingerprint, fp->length);
533*ebfedea0SLionel Sambuc }
534*ebfedea0SLionel Sambuc }
535*ebfedea0SLionel Sambuc return 1;
536*ebfedea0SLionel Sambuc }
537*ebfedea0SLionel Sambuc
538*ebfedea0SLionel Sambuc /**
539*ebfedea0SLionel Sambuc * \ingroup Core_Keys
540*ebfedea0SLionel Sambuc * \brief Calculate the Key ID from the public key.
541*ebfedea0SLionel Sambuc * \param keyid Space for the calculated ID to be stored
542*ebfedea0SLionel Sambuc * \param key The key for which the ID is calculated
543*ebfedea0SLionel Sambuc */
544*ebfedea0SLionel Sambuc
545*ebfedea0SLionel Sambuc int
pgp_keyid(uint8_t * keyid,const size_t idlen,const pgp_pubkey_t * key,pgp_hash_alg_t hashtype)546*ebfedea0SLionel Sambuc pgp_keyid(uint8_t *keyid, const size_t idlen, const pgp_pubkey_t *key, pgp_hash_alg_t hashtype)
547*ebfedea0SLionel Sambuc {
548*ebfedea0SLionel Sambuc pgp_fingerprint_t finger;
549*ebfedea0SLionel Sambuc
550*ebfedea0SLionel Sambuc if (key->version == 2 || key->version == 3) {
551*ebfedea0SLionel Sambuc unsigned n;
552*ebfedea0SLionel Sambuc uint8_t bn[NETPGP_BUFSIZ];
553*ebfedea0SLionel Sambuc
554*ebfedea0SLionel Sambuc n = (unsigned) BN_num_bytes(key->key.rsa.n);
555*ebfedea0SLionel Sambuc if (n > sizeof(bn)) {
556*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_keyid: bad num bytes\n");
557*ebfedea0SLionel Sambuc return 0;
558*ebfedea0SLionel Sambuc }
559*ebfedea0SLionel Sambuc if (key->alg != PGP_PKA_RSA &&
560*ebfedea0SLionel Sambuc key->alg != PGP_PKA_RSA_ENCRYPT_ONLY &&
561*ebfedea0SLionel Sambuc key->alg != PGP_PKA_RSA_SIGN_ONLY) {
562*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_keyid: bad algorithm\n");
563*ebfedea0SLionel Sambuc return 0;
564*ebfedea0SLionel Sambuc }
565*ebfedea0SLionel Sambuc BN_bn2bin(key->key.rsa.n, bn);
566*ebfedea0SLionel Sambuc (void) memcpy(keyid, bn + n - idlen, idlen);
567*ebfedea0SLionel Sambuc } else {
568*ebfedea0SLionel Sambuc pgp_fingerprint(&finger, key, hashtype);
569*ebfedea0SLionel Sambuc (void) memcpy(keyid,
570*ebfedea0SLionel Sambuc finger.fingerprint + finger.length - idlen,
571*ebfedea0SLionel Sambuc idlen);
572*ebfedea0SLionel Sambuc }
573*ebfedea0SLionel Sambuc return 1;
574*ebfedea0SLionel Sambuc }
575*ebfedea0SLionel Sambuc
576*ebfedea0SLionel Sambuc /**
577*ebfedea0SLionel Sambuc \ingroup Core_Hashes
578*ebfedea0SLionel Sambuc \brief Add to the hash
579*ebfedea0SLionel Sambuc \param hash Hash to add to
580*ebfedea0SLionel Sambuc \param n Int to add
581*ebfedea0SLionel Sambuc \param length Length of int in bytes
582*ebfedea0SLionel Sambuc */
583*ebfedea0SLionel Sambuc void
pgp_hash_add_int(pgp_hash_t * hash,unsigned n,unsigned length)584*ebfedea0SLionel Sambuc pgp_hash_add_int(pgp_hash_t *hash, unsigned n, unsigned length)
585*ebfedea0SLionel Sambuc {
586*ebfedea0SLionel Sambuc uint8_t c;
587*ebfedea0SLionel Sambuc
588*ebfedea0SLionel Sambuc while (length--) {
589*ebfedea0SLionel Sambuc c = n >> (length * 8);
590*ebfedea0SLionel Sambuc hash->add(hash, &c, 1);
591*ebfedea0SLionel Sambuc }
592*ebfedea0SLionel Sambuc }
593*ebfedea0SLionel Sambuc
594*ebfedea0SLionel Sambuc /**
595*ebfedea0SLionel Sambuc \ingroup Core_Hashes
596*ebfedea0SLionel Sambuc \brief Setup hash for given hash algorithm
597*ebfedea0SLionel Sambuc \param hash Hash to set up
598*ebfedea0SLionel Sambuc \param alg Hash algorithm to use
599*ebfedea0SLionel Sambuc */
600*ebfedea0SLionel Sambuc void
pgp_hash_any(pgp_hash_t * hash,pgp_hash_alg_t alg)601*ebfedea0SLionel Sambuc pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg)
602*ebfedea0SLionel Sambuc {
603*ebfedea0SLionel Sambuc switch (alg) {
604*ebfedea0SLionel Sambuc case PGP_HASH_MD5:
605*ebfedea0SLionel Sambuc pgp_hash_md5(hash);
606*ebfedea0SLionel Sambuc break;
607*ebfedea0SLionel Sambuc
608*ebfedea0SLionel Sambuc case PGP_HASH_SHA1:
609*ebfedea0SLionel Sambuc pgp_hash_sha1(hash);
610*ebfedea0SLionel Sambuc break;
611*ebfedea0SLionel Sambuc
612*ebfedea0SLionel Sambuc case PGP_HASH_SHA256:
613*ebfedea0SLionel Sambuc pgp_hash_sha256(hash);
614*ebfedea0SLionel Sambuc break;
615*ebfedea0SLionel Sambuc
616*ebfedea0SLionel Sambuc case PGP_HASH_SHA384:
617*ebfedea0SLionel Sambuc pgp_hash_sha384(hash);
618*ebfedea0SLionel Sambuc break;
619*ebfedea0SLionel Sambuc
620*ebfedea0SLionel Sambuc case PGP_HASH_SHA512:
621*ebfedea0SLionel Sambuc pgp_hash_sha512(hash);
622*ebfedea0SLionel Sambuc break;
623*ebfedea0SLionel Sambuc
624*ebfedea0SLionel Sambuc case PGP_HASH_SHA224:
625*ebfedea0SLionel Sambuc pgp_hash_sha224(hash);
626*ebfedea0SLionel Sambuc break;
627*ebfedea0SLionel Sambuc
628*ebfedea0SLionel Sambuc default:
629*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_hash_any: bad algorithm\n");
630*ebfedea0SLionel Sambuc }
631*ebfedea0SLionel Sambuc }
632*ebfedea0SLionel Sambuc
633*ebfedea0SLionel Sambuc /**
634*ebfedea0SLionel Sambuc \ingroup Core_Hashes
635*ebfedea0SLionel Sambuc \brief Returns size of hash for given hash algorithm
636*ebfedea0SLionel Sambuc \param alg Hash algorithm to use
637*ebfedea0SLionel Sambuc \return Size of hash algorithm in bytes
638*ebfedea0SLionel Sambuc */
639*ebfedea0SLionel Sambuc unsigned
pgp_hash_size(pgp_hash_alg_t alg)640*ebfedea0SLionel Sambuc pgp_hash_size(pgp_hash_alg_t alg)
641*ebfedea0SLionel Sambuc {
642*ebfedea0SLionel Sambuc switch (alg) {
643*ebfedea0SLionel Sambuc case PGP_HASH_MD5:
644*ebfedea0SLionel Sambuc return 16;
645*ebfedea0SLionel Sambuc
646*ebfedea0SLionel Sambuc case PGP_HASH_SHA1:
647*ebfedea0SLionel Sambuc return 20;
648*ebfedea0SLionel Sambuc
649*ebfedea0SLionel Sambuc case PGP_HASH_SHA256:
650*ebfedea0SLionel Sambuc return 32;
651*ebfedea0SLionel Sambuc
652*ebfedea0SLionel Sambuc case PGP_HASH_SHA224:
653*ebfedea0SLionel Sambuc return 28;
654*ebfedea0SLionel Sambuc
655*ebfedea0SLionel Sambuc case PGP_HASH_SHA512:
656*ebfedea0SLionel Sambuc return 64;
657*ebfedea0SLionel Sambuc
658*ebfedea0SLionel Sambuc case PGP_HASH_SHA384:
659*ebfedea0SLionel Sambuc return 48;
660*ebfedea0SLionel Sambuc
661*ebfedea0SLionel Sambuc default:
662*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_hash_size: bad algorithm\n");
663*ebfedea0SLionel Sambuc }
664*ebfedea0SLionel Sambuc
665*ebfedea0SLionel Sambuc return 0;
666*ebfedea0SLionel Sambuc }
667*ebfedea0SLionel Sambuc
668*ebfedea0SLionel Sambuc /**
669*ebfedea0SLionel Sambuc \ingroup Core_Hashes
670*ebfedea0SLionel Sambuc \brief Returns hash enum corresponding to given string
671*ebfedea0SLionel Sambuc \param hash Text name of hash algorithm i.e. "SHA1"
672*ebfedea0SLionel Sambuc \returns Corresponding enum i.e. PGP_HASH_SHA1
673*ebfedea0SLionel Sambuc */
674*ebfedea0SLionel Sambuc pgp_hash_alg_t
pgp_str_to_hash_alg(const char * hash)675*ebfedea0SLionel Sambuc pgp_str_to_hash_alg(const char *hash)
676*ebfedea0SLionel Sambuc {
677*ebfedea0SLionel Sambuc if (hash == NULL) {
678*ebfedea0SLionel Sambuc return PGP_DEFAULT_HASH_ALGORITHM;
679*ebfedea0SLionel Sambuc }
680*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(hash, "SHA1") == 0) {
681*ebfedea0SLionel Sambuc return PGP_HASH_SHA1;
682*ebfedea0SLionel Sambuc }
683*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(hash, "MD5") == 0) {
684*ebfedea0SLionel Sambuc return PGP_HASH_MD5;
685*ebfedea0SLionel Sambuc }
686*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(hash, "SHA256") == 0) {
687*ebfedea0SLionel Sambuc return PGP_HASH_SHA256;
688*ebfedea0SLionel Sambuc }
689*ebfedea0SLionel Sambuc /*
690*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(hash,"SHA224") == 0) {
691*ebfedea0SLionel Sambuc return PGP_HASH_SHA224;
692*ebfedea0SLionel Sambuc }
693*ebfedea0SLionel Sambuc */
694*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(hash, "SHA512") == 0) {
695*ebfedea0SLionel Sambuc return PGP_HASH_SHA512;
696*ebfedea0SLionel Sambuc }
697*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(hash, "SHA384") == 0) {
698*ebfedea0SLionel Sambuc return PGP_HASH_SHA384;
699*ebfedea0SLionel Sambuc }
700*ebfedea0SLionel Sambuc return PGP_HASH_UNKNOWN;
701*ebfedea0SLionel Sambuc }
702*ebfedea0SLionel Sambuc
703*ebfedea0SLionel Sambuc /**
704*ebfedea0SLionel Sambuc \ingroup Core_Hashes
705*ebfedea0SLionel Sambuc \brief Hash given data
706*ebfedea0SLionel Sambuc \param out Where to write the hash
707*ebfedea0SLionel Sambuc \param alg Hash algorithm to use
708*ebfedea0SLionel Sambuc \param in Data to hash
709*ebfedea0SLionel Sambuc \param length Length of data
710*ebfedea0SLionel Sambuc \return Size of hash created
711*ebfedea0SLionel Sambuc */
712*ebfedea0SLionel Sambuc unsigned
pgp_hash(uint8_t * out,pgp_hash_alg_t alg,const void * in,size_t length)713*ebfedea0SLionel Sambuc pgp_hash(uint8_t *out, pgp_hash_alg_t alg, const void *in, size_t length)
714*ebfedea0SLionel Sambuc {
715*ebfedea0SLionel Sambuc pgp_hash_t hash;
716*ebfedea0SLionel Sambuc
717*ebfedea0SLionel Sambuc pgp_hash_any(&hash, alg);
718*ebfedea0SLionel Sambuc if (!hash.init(&hash)) {
719*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_hash: bad alloc\n");
720*ebfedea0SLionel Sambuc /* we'll just continue here - don't want to return a 0 hash */
721*ebfedea0SLionel Sambuc /* XXX - agc - no way to return failure */
722*ebfedea0SLionel Sambuc }
723*ebfedea0SLionel Sambuc hash.add(&hash, in, (unsigned)length);
724*ebfedea0SLionel Sambuc return hash.finish(&hash, out);
725*ebfedea0SLionel Sambuc }
726*ebfedea0SLionel Sambuc
727*ebfedea0SLionel Sambuc /**
728*ebfedea0SLionel Sambuc \ingroup Core_Hashes
729*ebfedea0SLionel Sambuc \brief Calculate hash for MDC packet
730*ebfedea0SLionel Sambuc \param preamble Preamble to hash
731*ebfedea0SLionel Sambuc \param sz_preamble Size of preamble
732*ebfedea0SLionel Sambuc \param plaintext Plaintext to hash
733*ebfedea0SLionel Sambuc \param sz_plaintext Size of plaintext
734*ebfedea0SLionel Sambuc \param hashed Resulting hash
735*ebfedea0SLionel Sambuc */
736*ebfedea0SLionel Sambuc void
pgp_calc_mdc_hash(const uint8_t * preamble,const size_t sz_preamble,const uint8_t * plaintext,const unsigned sz_plaintext,uint8_t * hashed)737*ebfedea0SLionel Sambuc pgp_calc_mdc_hash(const uint8_t *preamble,
738*ebfedea0SLionel Sambuc const size_t sz_preamble,
739*ebfedea0SLionel Sambuc const uint8_t *plaintext,
740*ebfedea0SLionel Sambuc const unsigned sz_plaintext,
741*ebfedea0SLionel Sambuc uint8_t *hashed)
742*ebfedea0SLionel Sambuc {
743*ebfedea0SLionel Sambuc pgp_hash_t hash;
744*ebfedea0SLionel Sambuc uint8_t c;
745*ebfedea0SLionel Sambuc
746*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
747*ebfedea0SLionel Sambuc hexdump(stderr, "preamble", preamble, sz_preamble);
748*ebfedea0SLionel Sambuc hexdump(stderr, "plaintext", plaintext, sz_plaintext);
749*ebfedea0SLionel Sambuc }
750*ebfedea0SLionel Sambuc /* init */
751*ebfedea0SLionel Sambuc pgp_hash_any(&hash, PGP_HASH_SHA1);
752*ebfedea0SLionel Sambuc if (!hash.init(&hash)) {
753*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_calc_mdc_hash: bad alloc\n");
754*ebfedea0SLionel Sambuc /* we'll just continue here - it will die anyway */
755*ebfedea0SLionel Sambuc /* agc - XXX - no way to return failure */
756*ebfedea0SLionel Sambuc }
757*ebfedea0SLionel Sambuc
758*ebfedea0SLionel Sambuc /* preamble */
759*ebfedea0SLionel Sambuc hash.add(&hash, preamble, (unsigned)sz_preamble);
760*ebfedea0SLionel Sambuc /* plaintext */
761*ebfedea0SLionel Sambuc hash.add(&hash, plaintext, sz_plaintext);
762*ebfedea0SLionel Sambuc /* MDC packet tag */
763*ebfedea0SLionel Sambuc c = MDC_PKT_TAG;
764*ebfedea0SLionel Sambuc hash.add(&hash, &c, 1);
765*ebfedea0SLionel Sambuc /* MDC packet len */
766*ebfedea0SLionel Sambuc c = PGP_SHA1_HASH_SIZE;
767*ebfedea0SLionel Sambuc hash.add(&hash, &c, 1);
768*ebfedea0SLionel Sambuc
769*ebfedea0SLionel Sambuc /* finish */
770*ebfedea0SLionel Sambuc hash.finish(&hash, hashed);
771*ebfedea0SLionel Sambuc
772*ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) {
773*ebfedea0SLionel Sambuc hexdump(stderr, "hashed", hashed, PGP_SHA1_HASH_SIZE);
774*ebfedea0SLionel Sambuc }
775*ebfedea0SLionel Sambuc }
776*ebfedea0SLionel Sambuc
777*ebfedea0SLionel Sambuc /**
778*ebfedea0SLionel Sambuc \ingroup HighLevel_Supported
779*ebfedea0SLionel Sambuc \brief Is this Hash Algorithm supported?
780*ebfedea0SLionel Sambuc \param hash_alg Hash Algorithm to check
781*ebfedea0SLionel Sambuc \return 1 if supported; else 0
782*ebfedea0SLionel Sambuc */
783*ebfedea0SLionel Sambuc unsigned
pgp_is_hash_alg_supported(const pgp_hash_alg_t * hash_alg)784*ebfedea0SLionel Sambuc pgp_is_hash_alg_supported(const pgp_hash_alg_t *hash_alg)
785*ebfedea0SLionel Sambuc {
786*ebfedea0SLionel Sambuc switch (*hash_alg) {
787*ebfedea0SLionel Sambuc case PGP_HASH_MD5:
788*ebfedea0SLionel Sambuc case PGP_HASH_SHA1:
789*ebfedea0SLionel Sambuc case PGP_HASH_SHA256:
790*ebfedea0SLionel Sambuc return 1;
791*ebfedea0SLionel Sambuc
792*ebfedea0SLionel Sambuc default:
793*ebfedea0SLionel Sambuc return 0;
794*ebfedea0SLionel Sambuc }
795*ebfedea0SLionel Sambuc }
796*ebfedea0SLionel Sambuc
797*ebfedea0SLionel Sambuc /* structure to map string to cipher def */
798*ebfedea0SLionel Sambuc typedef struct str2cipher_t {
799*ebfedea0SLionel Sambuc const char *s; /* cipher name */
800*ebfedea0SLionel Sambuc pgp_symm_alg_t i; /* cipher def */
801*ebfedea0SLionel Sambuc } str2cipher_t;
802*ebfedea0SLionel Sambuc
803*ebfedea0SLionel Sambuc static str2cipher_t str2cipher[] = {
804*ebfedea0SLionel Sambuc { "cast5", PGP_SA_CAST5 },
805*ebfedea0SLionel Sambuc { "idea", PGP_SA_IDEA },
806*ebfedea0SLionel Sambuc { "aes128", PGP_SA_AES_128 },
807*ebfedea0SLionel Sambuc { "aes256", PGP_SA_AES_256 },
808*ebfedea0SLionel Sambuc { "camellia128", PGP_SA_CAMELLIA_128 },
809*ebfedea0SLionel Sambuc { "camellia256", PGP_SA_CAMELLIA_256 },
810*ebfedea0SLionel Sambuc { "tripledes", PGP_SA_TRIPLEDES },
811*ebfedea0SLionel Sambuc { NULL, 0 }
812*ebfedea0SLionel Sambuc };
813*ebfedea0SLionel Sambuc
814*ebfedea0SLionel Sambuc /* convert from a string to a cipher definition */
815*ebfedea0SLionel Sambuc pgp_symm_alg_t
pgp_str_to_cipher(const char * cipher)816*ebfedea0SLionel Sambuc pgp_str_to_cipher(const char *cipher)
817*ebfedea0SLionel Sambuc {
818*ebfedea0SLionel Sambuc str2cipher_t *sp;
819*ebfedea0SLionel Sambuc
820*ebfedea0SLionel Sambuc for (sp = str2cipher ; cipher && sp->s ; sp++) {
821*ebfedea0SLionel Sambuc if (netpgp_strcasecmp(cipher, sp->s) == 0) {
822*ebfedea0SLionel Sambuc return sp->i;
823*ebfedea0SLionel Sambuc }
824*ebfedea0SLionel Sambuc }
825*ebfedea0SLionel Sambuc return PGP_SA_DEFAULT_CIPHER;
826*ebfedea0SLionel Sambuc }
827*ebfedea0SLionel Sambuc
828*ebfedea0SLionel Sambuc void
pgp_random(void * dest,size_t length)829*ebfedea0SLionel Sambuc pgp_random(void *dest, size_t length)
830*ebfedea0SLionel Sambuc {
831*ebfedea0SLionel Sambuc RAND_bytes(dest, (int)length);
832*ebfedea0SLionel Sambuc }
833*ebfedea0SLionel Sambuc
834*ebfedea0SLionel Sambuc /**
835*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
836*ebfedea0SLionel Sambuc \brief Memory to initialise
837*ebfedea0SLionel Sambuc \param mem memory to initialise
838*ebfedea0SLionel Sambuc \param needed Size to initialise to
839*ebfedea0SLionel Sambuc */
840*ebfedea0SLionel Sambuc void
pgp_memory_init(pgp_memory_t * mem,size_t needed)841*ebfedea0SLionel Sambuc pgp_memory_init(pgp_memory_t *mem, size_t needed)
842*ebfedea0SLionel Sambuc {
843*ebfedea0SLionel Sambuc uint8_t *temp;
844*ebfedea0SLionel Sambuc
845*ebfedea0SLionel Sambuc mem->length = 0;
846*ebfedea0SLionel Sambuc if (mem->buf) {
847*ebfedea0SLionel Sambuc if (mem->allocated < needed) {
848*ebfedea0SLionel Sambuc if ((temp = realloc(mem->buf, needed)) == NULL) {
849*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_memory_init: bad alloc\n");
850*ebfedea0SLionel Sambuc } else {
851*ebfedea0SLionel Sambuc mem->buf = temp;
852*ebfedea0SLionel Sambuc mem->allocated = needed;
853*ebfedea0SLionel Sambuc }
854*ebfedea0SLionel Sambuc }
855*ebfedea0SLionel Sambuc } else {
856*ebfedea0SLionel Sambuc if ((mem->buf = calloc(1, needed)) == NULL) {
857*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_memory_init: bad alloc\n");
858*ebfedea0SLionel Sambuc } else {
859*ebfedea0SLionel Sambuc mem->allocated = needed;
860*ebfedea0SLionel Sambuc }
861*ebfedea0SLionel Sambuc }
862*ebfedea0SLionel Sambuc }
863*ebfedea0SLionel Sambuc
864*ebfedea0SLionel Sambuc /**
865*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
866*ebfedea0SLionel Sambuc \brief Pad memory to required length
867*ebfedea0SLionel Sambuc \param mem Memory to use
868*ebfedea0SLionel Sambuc \param length New size
869*ebfedea0SLionel Sambuc */
870*ebfedea0SLionel Sambuc void
pgp_memory_pad(pgp_memory_t * mem,size_t length)871*ebfedea0SLionel Sambuc pgp_memory_pad(pgp_memory_t *mem, size_t length)
872*ebfedea0SLionel Sambuc {
873*ebfedea0SLionel Sambuc uint8_t *temp;
874*ebfedea0SLionel Sambuc
875*ebfedea0SLionel Sambuc if (mem->allocated < mem->length) {
876*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_memory_pad: bad alloc in\n");
877*ebfedea0SLionel Sambuc return;
878*ebfedea0SLionel Sambuc }
879*ebfedea0SLionel Sambuc if (mem->allocated < mem->length + length) {
880*ebfedea0SLionel Sambuc mem->allocated = mem->allocated * 2 + length;
881*ebfedea0SLionel Sambuc temp = realloc(mem->buf, mem->allocated);
882*ebfedea0SLionel Sambuc if (temp == NULL) {
883*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_memory_pad: bad alloc\n");
884*ebfedea0SLionel Sambuc } else {
885*ebfedea0SLionel Sambuc mem->buf = temp;
886*ebfedea0SLionel Sambuc }
887*ebfedea0SLionel Sambuc }
888*ebfedea0SLionel Sambuc if (mem->allocated < mem->length + length) {
889*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_memory_pad: bad alloc out\n");
890*ebfedea0SLionel Sambuc }
891*ebfedea0SLionel Sambuc }
892*ebfedea0SLionel Sambuc
893*ebfedea0SLionel Sambuc /**
894*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
895*ebfedea0SLionel Sambuc \brief Add data to memory
896*ebfedea0SLionel Sambuc \param mem Memory to which to add
897*ebfedea0SLionel Sambuc \param src Data to add
898*ebfedea0SLionel Sambuc \param length Length of data to add
899*ebfedea0SLionel Sambuc */
900*ebfedea0SLionel Sambuc void
pgp_memory_add(pgp_memory_t * mem,const uint8_t * src,size_t length)901*ebfedea0SLionel Sambuc pgp_memory_add(pgp_memory_t *mem, const uint8_t *src, size_t length)
902*ebfedea0SLionel Sambuc {
903*ebfedea0SLionel Sambuc pgp_memory_pad(mem, length);
904*ebfedea0SLionel Sambuc (void) memcpy(mem->buf + mem->length, src, length);
905*ebfedea0SLionel Sambuc mem->length += length;
906*ebfedea0SLionel Sambuc }
907*ebfedea0SLionel Sambuc
908*ebfedea0SLionel Sambuc /* XXX: this could be refactored via the writer, but an awful lot of */
909*ebfedea0SLionel Sambuc /* hoops to jump through for 2 lines of code! */
910*ebfedea0SLionel Sambuc void
pgp_memory_place_int(pgp_memory_t * mem,unsigned offset,unsigned n,size_t length)911*ebfedea0SLionel Sambuc pgp_memory_place_int(pgp_memory_t *mem, unsigned offset, unsigned n,
912*ebfedea0SLionel Sambuc size_t length)
913*ebfedea0SLionel Sambuc {
914*ebfedea0SLionel Sambuc if (mem->allocated < offset + length) {
915*ebfedea0SLionel Sambuc (void) fprintf(stderr,
916*ebfedea0SLionel Sambuc "pgp_memory_place_int: bad alloc\n");
917*ebfedea0SLionel Sambuc } else {
918*ebfedea0SLionel Sambuc while (length-- > 0) {
919*ebfedea0SLionel Sambuc mem->buf[offset++] = n >> (length * 8);
920*ebfedea0SLionel Sambuc }
921*ebfedea0SLionel Sambuc }
922*ebfedea0SLionel Sambuc }
923*ebfedea0SLionel Sambuc
924*ebfedea0SLionel Sambuc /**
925*ebfedea0SLionel Sambuc * \ingroup HighLevel_Memory
926*ebfedea0SLionel Sambuc * \brief Retains allocated memory and set length of stored data to zero.
927*ebfedea0SLionel Sambuc * \param mem Memory to clear
928*ebfedea0SLionel Sambuc * \sa pgp_memory_release()
929*ebfedea0SLionel Sambuc * \sa pgp_memory_free()
930*ebfedea0SLionel Sambuc */
931*ebfedea0SLionel Sambuc void
pgp_memory_clear(pgp_memory_t * mem)932*ebfedea0SLionel Sambuc pgp_memory_clear(pgp_memory_t *mem)
933*ebfedea0SLionel Sambuc {
934*ebfedea0SLionel Sambuc mem->length = 0;
935*ebfedea0SLionel Sambuc }
936*ebfedea0SLionel Sambuc
937*ebfedea0SLionel Sambuc /**
938*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
939*ebfedea0SLionel Sambuc \brief Free memory and associated data
940*ebfedea0SLionel Sambuc \param mem Memory to free
941*ebfedea0SLionel Sambuc \note This does not free mem itself
942*ebfedea0SLionel Sambuc \sa pgp_memory_clear()
943*ebfedea0SLionel Sambuc \sa pgp_memory_free()
944*ebfedea0SLionel Sambuc */
945*ebfedea0SLionel Sambuc void
pgp_memory_release(pgp_memory_t * mem)946*ebfedea0SLionel Sambuc pgp_memory_release(pgp_memory_t *mem)
947*ebfedea0SLionel Sambuc {
948*ebfedea0SLionel Sambuc if (mem->mmapped) {
949*ebfedea0SLionel Sambuc (void) munmap(mem->buf, mem->length);
950*ebfedea0SLionel Sambuc } else {
951*ebfedea0SLionel Sambuc free(mem->buf);
952*ebfedea0SLionel Sambuc }
953*ebfedea0SLionel Sambuc mem->buf = NULL;
954*ebfedea0SLionel Sambuc mem->length = 0;
955*ebfedea0SLionel Sambuc }
956*ebfedea0SLionel Sambuc
957*ebfedea0SLionel Sambuc void
pgp_memory_make_packet(pgp_memory_t * out,pgp_content_enum tag)958*ebfedea0SLionel Sambuc pgp_memory_make_packet(pgp_memory_t *out, pgp_content_enum tag)
959*ebfedea0SLionel Sambuc {
960*ebfedea0SLionel Sambuc size_t extra;
961*ebfedea0SLionel Sambuc
962*ebfedea0SLionel Sambuc extra = (out->length < 192) ? 1 : (out->length < 8192 + 192) ? 2 : 5;
963*ebfedea0SLionel Sambuc pgp_memory_pad(out, extra + 1);
964*ebfedea0SLionel Sambuc memmove(out->buf + extra + 1, out->buf, out->length);
965*ebfedea0SLionel Sambuc
966*ebfedea0SLionel Sambuc out->buf[0] = PGP_PTAG_ALWAYS_SET | PGP_PTAG_NEW_FORMAT | tag;
967*ebfedea0SLionel Sambuc
968*ebfedea0SLionel Sambuc if (out->length < 192) {
969*ebfedea0SLionel Sambuc out->buf[1] = (uint8_t)out->length;
970*ebfedea0SLionel Sambuc } else if (out->length < 8192 + 192) {
971*ebfedea0SLionel Sambuc out->buf[1] = (uint8_t)((out->length - 192) >> 8) + 192;
972*ebfedea0SLionel Sambuc out->buf[2] = (uint8_t)(out->length - 192);
973*ebfedea0SLionel Sambuc } else {
974*ebfedea0SLionel Sambuc out->buf[1] = 0xff;
975*ebfedea0SLionel Sambuc out->buf[2] = (uint8_t)(out->length >> 24);
976*ebfedea0SLionel Sambuc out->buf[3] = (uint8_t)(out->length >> 16);
977*ebfedea0SLionel Sambuc out->buf[4] = (uint8_t)(out->length >> 8);
978*ebfedea0SLionel Sambuc out->buf[5] = (uint8_t)(out->length);
979*ebfedea0SLionel Sambuc }
980*ebfedea0SLionel Sambuc
981*ebfedea0SLionel Sambuc out->length += extra + 1;
982*ebfedea0SLionel Sambuc }
983*ebfedea0SLionel Sambuc
984*ebfedea0SLionel Sambuc /**
985*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
986*ebfedea0SLionel Sambuc \brief Create a new zeroed pgp_memory_t
987*ebfedea0SLionel Sambuc \return Pointer to new pgp_memory_t
988*ebfedea0SLionel Sambuc \note Free using pgp_memory_free() after use.
989*ebfedea0SLionel Sambuc \sa pgp_memory_free()
990*ebfedea0SLionel Sambuc */
991*ebfedea0SLionel Sambuc
992*ebfedea0SLionel Sambuc pgp_memory_t *
pgp_memory_new(void)993*ebfedea0SLionel Sambuc pgp_memory_new(void)
994*ebfedea0SLionel Sambuc {
995*ebfedea0SLionel Sambuc return calloc(1, sizeof(pgp_memory_t));
996*ebfedea0SLionel Sambuc }
997*ebfedea0SLionel Sambuc
998*ebfedea0SLionel Sambuc /**
999*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
1000*ebfedea0SLionel Sambuc \brief Free memory ptr and associated memory
1001*ebfedea0SLionel Sambuc \param mem Memory to be freed
1002*ebfedea0SLionel Sambuc \sa pgp_memory_release()
1003*ebfedea0SLionel Sambuc \sa pgp_memory_clear()
1004*ebfedea0SLionel Sambuc */
1005*ebfedea0SLionel Sambuc
1006*ebfedea0SLionel Sambuc void
pgp_memory_free(pgp_memory_t * mem)1007*ebfedea0SLionel Sambuc pgp_memory_free(pgp_memory_t *mem)
1008*ebfedea0SLionel Sambuc {
1009*ebfedea0SLionel Sambuc pgp_memory_release(mem);
1010*ebfedea0SLionel Sambuc free(mem);
1011*ebfedea0SLionel Sambuc }
1012*ebfedea0SLionel Sambuc
1013*ebfedea0SLionel Sambuc /**
1014*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
1015*ebfedea0SLionel Sambuc \brief Get length of data stored in pgp_memory_t struct
1016*ebfedea0SLionel Sambuc \return Number of bytes in data
1017*ebfedea0SLionel Sambuc */
1018*ebfedea0SLionel Sambuc size_t
pgp_mem_len(const pgp_memory_t * mem)1019*ebfedea0SLionel Sambuc pgp_mem_len(const pgp_memory_t *mem)
1020*ebfedea0SLionel Sambuc {
1021*ebfedea0SLionel Sambuc return mem->length;
1022*ebfedea0SLionel Sambuc }
1023*ebfedea0SLionel Sambuc
1024*ebfedea0SLionel Sambuc /**
1025*ebfedea0SLionel Sambuc \ingroup HighLevel_Memory
1026*ebfedea0SLionel Sambuc \brief Get data stored in pgp_memory_t struct
1027*ebfedea0SLionel Sambuc \return Pointer to data
1028*ebfedea0SLionel Sambuc */
1029*ebfedea0SLionel Sambuc void *
pgp_mem_data(pgp_memory_t * mem)1030*ebfedea0SLionel Sambuc pgp_mem_data(pgp_memory_t *mem)
1031*ebfedea0SLionel Sambuc {
1032*ebfedea0SLionel Sambuc return mem->buf;
1033*ebfedea0SLionel Sambuc }
1034*ebfedea0SLionel Sambuc
1035*ebfedea0SLionel Sambuc /* read a gile into an pgp_memory_t */
1036*ebfedea0SLionel Sambuc int
pgp_mem_readfile(pgp_memory_t * mem,const char * f)1037*ebfedea0SLionel Sambuc pgp_mem_readfile(pgp_memory_t *mem, const char *f)
1038*ebfedea0SLionel Sambuc {
1039*ebfedea0SLionel Sambuc struct stat st;
1040*ebfedea0SLionel Sambuc FILE *fp;
1041*ebfedea0SLionel Sambuc int cc;
1042*ebfedea0SLionel Sambuc
1043*ebfedea0SLionel Sambuc if ((fp = fopen(f, "rb")) == NULL) {
1044*ebfedea0SLionel Sambuc (void) fprintf(stderr,
1045*ebfedea0SLionel Sambuc "pgp_mem_readfile: can't open \"%s\"\n", f);
1046*ebfedea0SLionel Sambuc return 0;
1047*ebfedea0SLionel Sambuc }
1048*ebfedea0SLionel Sambuc (void) fstat(fileno(fp), &st);
1049*ebfedea0SLionel Sambuc mem->allocated = (size_t)st.st_size;
1050*ebfedea0SLionel Sambuc mem->buf = mmap(NULL, mem->allocated, PROT_READ,
1051*ebfedea0SLionel Sambuc MAP_PRIVATE | MAP_FILE, fileno(fp), 0);
1052*ebfedea0SLionel Sambuc if (mem->buf == MAP_FAILED) {
1053*ebfedea0SLionel Sambuc /* mmap failed for some reason - try to allocate memory */
1054*ebfedea0SLionel Sambuc if ((mem->buf = calloc(1, mem->allocated)) == NULL) {
1055*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_mem_readfile: calloc\n");
1056*ebfedea0SLionel Sambuc (void) fclose(fp);
1057*ebfedea0SLionel Sambuc return 0;
1058*ebfedea0SLionel Sambuc }
1059*ebfedea0SLionel Sambuc /* read into contents of mem */
1060*ebfedea0SLionel Sambuc for (mem->length = 0 ;
1061*ebfedea0SLionel Sambuc (cc = (int)read(fileno(fp), &mem->buf[mem->length],
1062*ebfedea0SLionel Sambuc (size_t)(mem->allocated - mem->length))) > 0 ;
1063*ebfedea0SLionel Sambuc mem->length += (size_t)cc) {
1064*ebfedea0SLionel Sambuc }
1065*ebfedea0SLionel Sambuc } else {
1066*ebfedea0SLionel Sambuc mem->length = mem->allocated;
1067*ebfedea0SLionel Sambuc mem->mmapped = 1;
1068*ebfedea0SLionel Sambuc }
1069*ebfedea0SLionel Sambuc (void) fclose(fp);
1070*ebfedea0SLionel Sambuc return (mem->allocated == mem->length);
1071*ebfedea0SLionel Sambuc }
1072*ebfedea0SLionel Sambuc
1073*ebfedea0SLionel Sambuc typedef struct {
1074*ebfedea0SLionel Sambuc uint16_t sum;
1075*ebfedea0SLionel Sambuc } sum16_t;
1076*ebfedea0SLionel Sambuc
1077*ebfedea0SLionel Sambuc
1078*ebfedea0SLionel Sambuc /**
1079*ebfedea0SLionel Sambuc * Searches the given map for the given type.
1080*ebfedea0SLionel Sambuc * Returns a human-readable descriptive string if found,
1081*ebfedea0SLionel Sambuc * returns NULL if not found
1082*ebfedea0SLionel Sambuc *
1083*ebfedea0SLionel Sambuc * It is the responsibility of the calling function to handle the
1084*ebfedea0SLionel Sambuc * error case sensibly (i.e. don't just print out the return string.
1085*ebfedea0SLionel Sambuc *
1086*ebfedea0SLionel Sambuc */
1087*ebfedea0SLionel Sambuc static const char *
str_from_map_or_null(int type,pgp_map_t * map)1088*ebfedea0SLionel Sambuc str_from_map_or_null(int type, pgp_map_t *map)
1089*ebfedea0SLionel Sambuc {
1090*ebfedea0SLionel Sambuc pgp_map_t *row;
1091*ebfedea0SLionel Sambuc
1092*ebfedea0SLionel Sambuc for (row = map; row->string != NULL; row++) {
1093*ebfedea0SLionel Sambuc if (row->type == type) {
1094*ebfedea0SLionel Sambuc return row->string;
1095*ebfedea0SLionel Sambuc }
1096*ebfedea0SLionel Sambuc }
1097*ebfedea0SLionel Sambuc return NULL;
1098*ebfedea0SLionel Sambuc }
1099*ebfedea0SLionel Sambuc
1100*ebfedea0SLionel Sambuc /**
1101*ebfedea0SLionel Sambuc * \ingroup Core_Print
1102*ebfedea0SLionel Sambuc *
1103*ebfedea0SLionel Sambuc * Searches the given map for the given type.
1104*ebfedea0SLionel Sambuc * Returns a readable string if found, "Unknown" if not.
1105*ebfedea0SLionel Sambuc */
1106*ebfedea0SLionel Sambuc
1107*ebfedea0SLionel Sambuc const char *
pgp_str_from_map(int type,pgp_map_t * map)1108*ebfedea0SLionel Sambuc pgp_str_from_map(int type, pgp_map_t *map)
1109*ebfedea0SLionel Sambuc {
1110*ebfedea0SLionel Sambuc const char *str;
1111*ebfedea0SLionel Sambuc
1112*ebfedea0SLionel Sambuc str = str_from_map_or_null(type, map);
1113*ebfedea0SLionel Sambuc return (str) ? str : "Unknown";
1114*ebfedea0SLionel Sambuc }
1115*ebfedea0SLionel Sambuc
1116*ebfedea0SLionel Sambuc #define LINELEN 16
1117*ebfedea0SLionel Sambuc
1118*ebfedea0SLionel Sambuc /* show hexadecimal/ascii dump */
1119*ebfedea0SLionel Sambuc void
hexdump(FILE * fp,const char * header,const uint8_t * src,size_t length)1120*ebfedea0SLionel Sambuc hexdump(FILE *fp, const char *header, const uint8_t *src, size_t length)
1121*ebfedea0SLionel Sambuc {
1122*ebfedea0SLionel Sambuc size_t i;
1123*ebfedea0SLionel Sambuc char line[LINELEN + 1];
1124*ebfedea0SLionel Sambuc
1125*ebfedea0SLionel Sambuc (void) fprintf(fp, "%s%s", (header) ? header : "", (header) ? "\n" : "");
1126*ebfedea0SLionel Sambuc (void) fprintf(fp, "[%" PRIsize "u char%s]\n", length, (length == 1) ? "" : "s");
1127*ebfedea0SLionel Sambuc for (i = 0 ; i < length ; i++) {
1128*ebfedea0SLionel Sambuc if (i % LINELEN == 0) {
1129*ebfedea0SLionel Sambuc (void) fprintf(fp, "%.5" PRIsize "u | ", i);
1130*ebfedea0SLionel Sambuc }
1131*ebfedea0SLionel Sambuc (void) fprintf(fp, "%.02x ", (uint8_t)src[i]);
1132*ebfedea0SLionel Sambuc line[i % LINELEN] = (isprint(src[i])) ? src[i] : '.';
1133*ebfedea0SLionel Sambuc if (i % LINELEN == LINELEN - 1) {
1134*ebfedea0SLionel Sambuc line[LINELEN] = 0x0;
1135*ebfedea0SLionel Sambuc (void) fprintf(fp, " | %s\n", line);
1136*ebfedea0SLionel Sambuc }
1137*ebfedea0SLionel Sambuc }
1138*ebfedea0SLionel Sambuc if (i % LINELEN != 0) {
1139*ebfedea0SLionel Sambuc for ( ; i % LINELEN != 0 ; i++) {
1140*ebfedea0SLionel Sambuc (void) fprintf(fp, " ");
1141*ebfedea0SLionel Sambuc line[i % LINELEN] = ' ';
1142*ebfedea0SLionel Sambuc }
1143*ebfedea0SLionel Sambuc line[LINELEN] = 0x0;
1144*ebfedea0SLionel Sambuc (void) fprintf(fp, " | %s\n", line);
1145*ebfedea0SLionel Sambuc }
1146*ebfedea0SLionel Sambuc }
1147*ebfedea0SLionel Sambuc
1148*ebfedea0SLionel Sambuc /**
1149*ebfedea0SLionel Sambuc * \ingroup HighLevel_Functions
1150*ebfedea0SLionel Sambuc * \brief Closes down OpenPGP::SDK.
1151*ebfedea0SLionel Sambuc *
1152*ebfedea0SLionel Sambuc * Close down OpenPGP:SDK, release any resources under the control of
1153*ebfedea0SLionel Sambuc * the library.
1154*ebfedea0SLionel Sambuc */
1155*ebfedea0SLionel Sambuc
1156*ebfedea0SLionel Sambuc void
pgp_finish(void)1157*ebfedea0SLionel Sambuc pgp_finish(void)
1158*ebfedea0SLionel Sambuc {
1159*ebfedea0SLionel Sambuc pgp_crypto_finish();
1160*ebfedea0SLionel Sambuc }
1161*ebfedea0SLionel Sambuc
1162*ebfedea0SLionel Sambuc static int
sum16_reader(pgp_stream_t * stream,void * dest_,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1163*ebfedea0SLionel Sambuc sum16_reader(pgp_stream_t *stream, void *dest_, size_t length, pgp_error_t **errors,
1164*ebfedea0SLionel Sambuc pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo)
1165*ebfedea0SLionel Sambuc {
1166*ebfedea0SLionel Sambuc const uint8_t *dest = dest_;
1167*ebfedea0SLionel Sambuc sum16_t *arg = pgp_reader_get_arg(readinfo);
1168*ebfedea0SLionel Sambuc int r;
1169*ebfedea0SLionel Sambuc int n;
1170*ebfedea0SLionel Sambuc
1171*ebfedea0SLionel Sambuc r = pgp_stacked_read(stream, dest_, length, errors, readinfo, cbinfo);
1172*ebfedea0SLionel Sambuc if (r < 0) {
1173*ebfedea0SLionel Sambuc return r;
1174*ebfedea0SLionel Sambuc }
1175*ebfedea0SLionel Sambuc for (n = 0; n < r; ++n) {
1176*ebfedea0SLionel Sambuc arg->sum = (arg->sum + dest[n]) & 0xffff;
1177*ebfedea0SLionel Sambuc }
1178*ebfedea0SLionel Sambuc return r;
1179*ebfedea0SLionel Sambuc }
1180*ebfedea0SLionel Sambuc
1181*ebfedea0SLionel Sambuc static void
sum16_destroyer(pgp_reader_t * readinfo)1182*ebfedea0SLionel Sambuc sum16_destroyer(pgp_reader_t *readinfo)
1183*ebfedea0SLionel Sambuc {
1184*ebfedea0SLionel Sambuc free(pgp_reader_get_arg(readinfo));
1185*ebfedea0SLionel Sambuc }
1186*ebfedea0SLionel Sambuc
1187*ebfedea0SLionel Sambuc /**
1188*ebfedea0SLionel Sambuc \ingroup Internal_Readers_Sum16
1189*ebfedea0SLionel Sambuc \param stream Parse settings
1190*ebfedea0SLionel Sambuc */
1191*ebfedea0SLionel Sambuc
1192*ebfedea0SLionel Sambuc void
pgp_reader_push_sum16(pgp_stream_t * stream)1193*ebfedea0SLionel Sambuc pgp_reader_push_sum16(pgp_stream_t *stream)
1194*ebfedea0SLionel Sambuc {
1195*ebfedea0SLionel Sambuc sum16_t *arg;
1196*ebfedea0SLionel Sambuc
1197*ebfedea0SLionel Sambuc if ((arg = calloc(1, sizeof(*arg))) == NULL) {
1198*ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_reader_push_sum16: bad alloc\n");
1199*ebfedea0SLionel Sambuc } else {
1200*ebfedea0SLionel Sambuc pgp_reader_push(stream, sum16_reader, sum16_destroyer, arg);
1201*ebfedea0SLionel Sambuc }
1202*ebfedea0SLionel Sambuc }
1203*ebfedea0SLionel Sambuc
1204*ebfedea0SLionel Sambuc /**
1205*ebfedea0SLionel Sambuc \ingroup Internal_Readers_Sum16
1206*ebfedea0SLionel Sambuc \param stream Parse settings
1207*ebfedea0SLionel Sambuc \return sum
1208*ebfedea0SLionel Sambuc */
1209*ebfedea0SLionel Sambuc uint16_t
pgp_reader_pop_sum16(pgp_stream_t * stream)1210*ebfedea0SLionel Sambuc pgp_reader_pop_sum16(pgp_stream_t *stream)
1211*ebfedea0SLionel Sambuc {
1212*ebfedea0SLionel Sambuc uint16_t sum;
1213*ebfedea0SLionel Sambuc sum16_t *arg;
1214*ebfedea0SLionel Sambuc
1215*ebfedea0SLionel Sambuc arg = pgp_reader_get_arg(pgp_readinfo(stream));
1216*ebfedea0SLionel Sambuc sum = arg->sum;
1217*ebfedea0SLionel Sambuc pgp_reader_pop(stream);
1218*ebfedea0SLionel Sambuc free(arg);
1219*ebfedea0SLionel Sambuc return sum;
1220*ebfedea0SLionel Sambuc }
1221*ebfedea0SLionel Sambuc
1222*ebfedea0SLionel Sambuc /* small useful functions for setting the file-level debugging levels */
1223*ebfedea0SLionel Sambuc /* if the debugv list contains the filename in question, we're debugging it */
1224*ebfedea0SLionel Sambuc
1225*ebfedea0SLionel Sambuc enum {
1226*ebfedea0SLionel Sambuc MAX_DEBUG_NAMES = 32
1227*ebfedea0SLionel Sambuc };
1228*ebfedea0SLionel Sambuc
1229*ebfedea0SLionel Sambuc static int debugc;
1230*ebfedea0SLionel Sambuc static char *debugv[MAX_DEBUG_NAMES];
1231*ebfedea0SLionel Sambuc
1232*ebfedea0SLionel Sambuc /* set the debugging level per filename */
1233*ebfedea0SLionel Sambuc int
pgp_set_debug_level(const char * f)1234*ebfedea0SLionel Sambuc pgp_set_debug_level(const char *f)
1235*ebfedea0SLionel Sambuc {
1236*ebfedea0SLionel Sambuc const char *name;
1237*ebfedea0SLionel Sambuc int i;
1238*ebfedea0SLionel Sambuc
1239*ebfedea0SLionel Sambuc if (f == NULL) {
1240*ebfedea0SLionel Sambuc f = "all";
1241*ebfedea0SLionel Sambuc }
1242*ebfedea0SLionel Sambuc if ((name = strrchr(f, '/')) == NULL) {
1243*ebfedea0SLionel Sambuc name = f;
1244*ebfedea0SLionel Sambuc } else {
1245*ebfedea0SLionel Sambuc name += 1;
1246*ebfedea0SLionel Sambuc }
1247*ebfedea0SLionel Sambuc for (i = 0; i < debugc && i < MAX_DEBUG_NAMES; i++) {
1248*ebfedea0SLionel Sambuc if (strcmp(debugv[i], name) == 0) {
1249*ebfedea0SLionel Sambuc return 1;
1250*ebfedea0SLionel Sambuc }
1251*ebfedea0SLionel Sambuc }
1252*ebfedea0SLionel Sambuc if (i == MAX_DEBUG_NAMES) {
1253*ebfedea0SLionel Sambuc return 0;
1254*ebfedea0SLionel Sambuc }
1255*ebfedea0SLionel Sambuc debugv[debugc++] = netpgp_strdup(name);
1256*ebfedea0SLionel Sambuc return 1;
1257*ebfedea0SLionel Sambuc }
1258*ebfedea0SLionel Sambuc
1259*ebfedea0SLionel Sambuc /* get the debugging level per filename */
1260*ebfedea0SLionel Sambuc int
pgp_get_debug_level(const char * f)1261*ebfedea0SLionel Sambuc pgp_get_debug_level(const char *f)
1262*ebfedea0SLionel Sambuc {
1263*ebfedea0SLionel Sambuc const char *name;
1264*ebfedea0SLionel Sambuc int i;
1265*ebfedea0SLionel Sambuc
1266*ebfedea0SLionel Sambuc if ((name = strrchr(f, '/')) == NULL) {
1267*ebfedea0SLionel Sambuc name = f;
1268*ebfedea0SLionel Sambuc } else {
1269*ebfedea0SLionel Sambuc name += 1;
1270*ebfedea0SLionel Sambuc }
1271*ebfedea0SLionel Sambuc for (i = 0; i < debugc; i++) {
1272*ebfedea0SLionel Sambuc if (strcmp(debugv[i], "all") == 0 ||
1273*ebfedea0SLionel Sambuc strcmp(debugv[i], name) == 0) {
1274*ebfedea0SLionel Sambuc return 1;
1275*ebfedea0SLionel Sambuc }
1276*ebfedea0SLionel Sambuc }
1277*ebfedea0SLionel Sambuc return 0;
1278*ebfedea0SLionel Sambuc }
1279*ebfedea0SLionel Sambuc
1280*ebfedea0SLionel Sambuc /* return the version for the library */
1281*ebfedea0SLionel Sambuc const char *
pgp_get_info(const char * type)1282*ebfedea0SLionel Sambuc pgp_get_info(const char *type)
1283*ebfedea0SLionel Sambuc {
1284*ebfedea0SLionel Sambuc if (strcmp(type, "version") == 0) {
1285*ebfedea0SLionel Sambuc return NETPGP_VERSION_STRING;
1286*ebfedea0SLionel Sambuc }
1287*ebfedea0SLionel Sambuc if (strcmp(type, "maintainer") == 0) {
1288*ebfedea0SLionel Sambuc return NETPGP_MAINTAINER;
1289*ebfedea0SLionel Sambuc }
1290*ebfedea0SLionel Sambuc return "[unknown]";
1291*ebfedea0SLionel Sambuc }
1292*ebfedea0SLionel Sambuc
1293*ebfedea0SLionel Sambuc /* local version of asprintf so we don't have to play autoconf games */
1294*ebfedea0SLionel Sambuc int
pgp_asprintf(char ** ret,const char * fmt,...)1295*ebfedea0SLionel Sambuc pgp_asprintf(char **ret, const char *fmt, ...)
1296*ebfedea0SLionel Sambuc {
1297*ebfedea0SLionel Sambuc va_list args;
1298*ebfedea0SLionel Sambuc char buf[120 * 1024]; /* XXX - "huge" buffer on stack */
1299*ebfedea0SLionel Sambuc int cc;
1300*ebfedea0SLionel Sambuc
1301*ebfedea0SLionel Sambuc va_start(args, fmt);
1302*ebfedea0SLionel Sambuc cc = vsnprintf(buf, sizeof(buf), fmt, args);
1303*ebfedea0SLionel Sambuc va_end(args);
1304*ebfedea0SLionel Sambuc if ((*ret = calloc(1, (size_t)(cc + 1))) == NULL) {
1305*ebfedea0SLionel Sambuc *ret = NULL;
1306*ebfedea0SLionel Sambuc return -1;
1307*ebfedea0SLionel Sambuc }
1308*ebfedea0SLionel Sambuc (void) memcpy(*ret, buf, (size_t)cc);
1309*ebfedea0SLionel Sambuc (*ret)[cc] = 0x0;
1310*ebfedea0SLionel Sambuc return cc;
1311*ebfedea0SLionel Sambuc }
1312*ebfedea0SLionel Sambuc
1313*ebfedea0SLionel Sambuc void
netpgp_log(const char * fmt,...)1314*ebfedea0SLionel Sambuc netpgp_log(const char *fmt, ...)
1315*ebfedea0SLionel Sambuc {
1316*ebfedea0SLionel Sambuc va_list vp;
1317*ebfedea0SLionel Sambuc time_t t;
1318*ebfedea0SLionel Sambuc char buf[BUFSIZ * 2];
1319*ebfedea0SLionel Sambuc int cc;
1320*ebfedea0SLionel Sambuc
1321*ebfedea0SLionel Sambuc (void) time(&t);
1322*ebfedea0SLionel Sambuc cc = snprintf(buf, sizeof(buf), "%.24s: netpgp: ", ctime(&t));
1323*ebfedea0SLionel Sambuc va_start(vp, fmt);
1324*ebfedea0SLionel Sambuc (void) vsnprintf(&buf[cc], sizeof(buf) - (size_t)cc, fmt, vp);
1325*ebfedea0SLionel Sambuc va_end(vp);
1326*ebfedea0SLionel Sambuc /* do something with message */
1327*ebfedea0SLionel Sambuc /* put into log buffer? */
1328*ebfedea0SLionel Sambuc }
1329*ebfedea0SLionel Sambuc
1330*ebfedea0SLionel Sambuc /* portable replacement for strdup(3) */
1331*ebfedea0SLionel Sambuc char *
netpgp_strdup(const char * s)1332*ebfedea0SLionel Sambuc netpgp_strdup(const char *s)
1333*ebfedea0SLionel Sambuc {
1334*ebfedea0SLionel Sambuc size_t len;
1335*ebfedea0SLionel Sambuc char *cp;
1336*ebfedea0SLionel Sambuc
1337*ebfedea0SLionel Sambuc len = strlen(s);
1338*ebfedea0SLionel Sambuc if ((cp = calloc(1, len + 1)) != NULL) {
1339*ebfedea0SLionel Sambuc (void) memcpy(cp, s, len);
1340*ebfedea0SLionel Sambuc cp[len] = 0x0;
1341*ebfedea0SLionel Sambuc }
1342*ebfedea0SLionel Sambuc return cp;
1343*ebfedea0SLionel Sambuc }
1344*ebfedea0SLionel Sambuc
1345*ebfedea0SLionel Sambuc /* portable replacement for strcasecmp(3) */
1346*ebfedea0SLionel Sambuc int
netpgp_strcasecmp(const char * s1,const char * s2)1347*ebfedea0SLionel Sambuc netpgp_strcasecmp(const char *s1, const char *s2)
1348*ebfedea0SLionel Sambuc {
1349*ebfedea0SLionel Sambuc int n;
1350*ebfedea0SLionel Sambuc
1351*ebfedea0SLionel Sambuc for (n = 0 ; *s1 && *s2 && (n = tolower((uint8_t)*s1) - tolower((uint8_t)*s2)) == 0 ; s1++, s2++) {
1352*ebfedea0SLionel Sambuc }
1353*ebfedea0SLionel Sambuc return n;
1354*ebfedea0SLionel Sambuc }
1355