1*3e07920fSDavid van Moolenbroek /* $NetBSD: sign.h,v 1.2 2008/11/07 07:36:38 minskim Exp $ */ 2*3e07920fSDavid van Moolenbroek 3*3e07920fSDavid van Moolenbroek /*- 4*3e07920fSDavid van Moolenbroek * Copyright (c) 2008 The NetBSD Foundation, Inc. 5*3e07920fSDavid van Moolenbroek * All rights reserved. 6*3e07920fSDavid van Moolenbroek * 7*3e07920fSDavid van Moolenbroek * This code is derived from software contributed to The NetBSD Foundation 8*3e07920fSDavid van Moolenbroek * by Martin Sch�tte. 9*3e07920fSDavid van Moolenbroek * 10*3e07920fSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without 11*3e07920fSDavid van Moolenbroek * modification, are permitted provided that the following conditions 12*3e07920fSDavid van Moolenbroek * are met: 13*3e07920fSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright 14*3e07920fSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer. 15*3e07920fSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright 16*3e07920fSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the 17*3e07920fSDavid van Moolenbroek * documentation and/or other materials provided with the distribution. 18*3e07920fSDavid van Moolenbroek * 3. All advertising materials mentioning features or use of this software 19*3e07920fSDavid van Moolenbroek * must display the following acknowledgement: 20*3e07920fSDavid van Moolenbroek * This product includes software developed by the NetBSD 21*3e07920fSDavid van Moolenbroek * Foundation, Inc. and its contributors. 22*3e07920fSDavid van Moolenbroek * 4. Neither the name of The NetBSD Foundation nor the names of its 23*3e07920fSDavid van Moolenbroek * contributors may be used to endorse or promote products derived 24*3e07920fSDavid van Moolenbroek * from this software without specific prior written permission. 25*3e07920fSDavid van Moolenbroek * 26*3e07920fSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27*3e07920fSDavid van Moolenbroek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28*3e07920fSDavid van Moolenbroek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29*3e07920fSDavid van Moolenbroek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30*3e07920fSDavid van Moolenbroek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31*3e07920fSDavid van Moolenbroek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32*3e07920fSDavid van Moolenbroek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33*3e07920fSDavid van Moolenbroek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34*3e07920fSDavid van Moolenbroek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35*3e07920fSDavid van Moolenbroek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36*3e07920fSDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGE. 37*3e07920fSDavid van Moolenbroek */ 38*3e07920fSDavid van Moolenbroek /* 39*3e07920fSDavid van Moolenbroek * sign.h 40*3e07920fSDavid van Moolenbroek * 41*3e07920fSDavid van Moolenbroek */ 42*3e07920fSDavid van Moolenbroek #ifndef SIGN_H_ 43*3e07920fSDavid van Moolenbroek #define SIGN_H_ 44*3e07920fSDavid van Moolenbroek 45*3e07920fSDavid van Moolenbroek #include <netinet/in.h> 46*3e07920fSDavid van Moolenbroek #include <resolv.h> 47*3e07920fSDavid van Moolenbroek #include <openssl/x509v3.h> 48*3e07920fSDavid van Moolenbroek #include <openssl/err.h> 49*3e07920fSDavid van Moolenbroek #include <openssl/rand.h> 50*3e07920fSDavid van Moolenbroek #include <openssl/pem.h> 51*3e07920fSDavid van Moolenbroek 52*3e07920fSDavid van Moolenbroek /* default Signature Group value, 53*3e07920fSDavid van Moolenbroek * defines signature strategy: 54*3e07920fSDavid van Moolenbroek * 0 one global SG 55*3e07920fSDavid van Moolenbroek * 1 one SG per PRI 56*3e07920fSDavid van Moolenbroek * 2 SGs for PRI ranges 57*3e07920fSDavid van Moolenbroek * 3 other (SGs not defined by PRI) 58*3e07920fSDavid van Moolenbroek * 59*3e07920fSDavid van Moolenbroek * We use '3' and assign one SG to every destination (=struct filed) 60*3e07920fSDavid van Moolenbroek */ 61*3e07920fSDavid van Moolenbroek #define SIGN_SG 3 62*3e07920fSDavid van Moolenbroek 63*3e07920fSDavid van Moolenbroek /* maximum value for several counters in -sign */ 64*3e07920fSDavid van Moolenbroek #define SIGN_MAX_COUNT 9999999999 65*3e07920fSDavid van Moolenbroek 66*3e07920fSDavid van Moolenbroek /* 67*3e07920fSDavid van Moolenbroek * many of these options could be made user configurable if desired, 68*3e07920fSDavid van Moolenbroek * but I do not see the need for that 69*3e07920fSDavid van Moolenbroek */ 70*3e07920fSDavid van Moolenbroek 71*3e07920fSDavid van Moolenbroek /* redundancy options */ 72*3e07920fSDavid van Moolenbroek /* 73*3e07920fSDavid van Moolenbroek * note on the implementation of redundancy: 74*3e07920fSDavid van Moolenbroek * - certificate blocks: sending the first CB just before first SB. 75*3e07920fSDavid van Moolenbroek * after that domark() triggers resends until resend count is reached. 76*3e07920fSDavid van Moolenbroek * - signature blocks: to send every hash n times I use a sliding window. 77*3e07920fSDavid van Moolenbroek * the hashes in every SB are grouped into n divisions: 78*3e07920fSDavid van Moolenbroek * * the 1st hashcount/n hashes are sent for the 1st time 79*3e07920fSDavid van Moolenbroek * * the 2nd hashcount/n hashes are sent for the 2nd time 80*3e07920fSDavid van Moolenbroek * * ... 81*3e07920fSDavid van Moolenbroek * * the n-th hashcount/n hashes are sent for the n-th time 82*3e07920fSDavid van Moolenbroek * (and deleted thereafter) 83*3e07920fSDavid van Moolenbroek */ 84*3e07920fSDavid van Moolenbroek #define SIGN_RESENDCOUNT_CERTBLOCK 2 85*3e07920fSDavid van Moolenbroek #define SIGN_RESENDCOUNT_HASHES 3 86*3e07920fSDavid van Moolenbroek 87*3e07920fSDavid van Moolenbroek /* maximum length of syslog-sign messages should be <= 2048 by standard 88*3e07920fSDavid van Moolenbroek * and should be >= 1024 to be long enough. 89*3e07920fSDavid van Moolenbroek * be careful with small values because there is no check for a lower bound 90*3e07920fSDavid van Moolenbroek * thus the following derived values would become negative. 91*3e07920fSDavid van Moolenbroek */ 92*3e07920fSDavid van Moolenbroek #define SIGN_MAX_LENGTH 2048 93*3e07920fSDavid van Moolenbroek /* the length we can use for the SD and keep the 94*3e07920fSDavid van Moolenbroek * message length with header below 2048 octets */ 95*3e07920fSDavid van Moolenbroek #define SIGN_MAX_SD_LENGTH (SIGN_MAX_LENGTH - 1 - HEADER_LEN_MAX) 96*3e07920fSDavid van Moolenbroek /* length of signature, currently only for DSA */ 97*3e07920fSDavid van Moolenbroek #define SIGN_B64SIGLEN_DSS 64+1 98*3e07920fSDavid van Moolenbroek /* the maximum length of one payload fragment: 99*3e07920fSDavid van Moolenbroek * max.SD len - text - max. field lengths - sig len */ 100*3e07920fSDavid van Moolenbroek #define SIGN_MAX_FRAG_LENGTH (SIGN_MAX_SD_LENGTH - 82 - 38 - SIGN_B64SIGLEN_DSS) 101*3e07920fSDavid van Moolenbroek /* the maximum length of one signature block: 102*3e07920fSDavid van Moolenbroek * max.SD len - text - max. field lens - sig len */ 103*3e07920fSDavid van Moolenbroek #define SIGN_MAX_SB_LENGTH (SIGN_MAX_SD_LENGTH - 72 - 40 - SIGN_B64SIGLEN_DSS) 104*3e07920fSDavid van Moolenbroek /* the maximum number of hashes pec signature block */ 105*3e07920fSDavid van Moolenbroek #define SIGN_MAX_HASH_NUM (SIGN_MAX_SB_LENGTH / (GlobalSign.md_len_b64+1)) 106*3e07920fSDavid van Moolenbroek /* number of hashes in one signature block */ 107*3e07920fSDavid van Moolenbroek #define SIGN_HASH_NUM_WANT 100 108*3e07920fSDavid van Moolenbroek /* make sure to consider SIGN_MAX_HASH_NUM and 109*3e07920fSDavid van Moolenbroek * to have a SIGN_HASH_NUM that is a multiple of SIGN_HASH_DIVISION_NUM */ 110*3e07920fSDavid van Moolenbroek #define SIGN_HASH_DIVISION_NUM (MIN(SIGN_HASH_NUM_WANT, SIGN_MAX_HASH_NUM) \ 111*3e07920fSDavid van Moolenbroek / SIGN_RESENDCOUNT_HASHES) 112*3e07920fSDavid van Moolenbroek #define SIGN_HASH_NUM (SIGN_HASH_DIVISION_NUM * SIGN_RESENDCOUNT_HASHES) 113*3e07920fSDavid van Moolenbroek 114*3e07920fSDavid van Moolenbroek /* the length of payload strings 115*3e07920fSDavid van Moolenbroek * since the payload is fragmented there is no technical limit 116*3e07920fSDavid van Moolenbroek * it just has to be big enough to hold big b64 encoded PKIX certificates 117*3e07920fSDavid van Moolenbroek */ 118*3e07920fSDavid van Moolenbroek #define SIGN_MAX_PAYLOAD_LENGTH 20480 119*3e07920fSDavid van Moolenbroek 120*3e07920fSDavid van Moolenbroek /* length of generated DSA keys for signing */ 121*3e07920fSDavid van Moolenbroek #define SIGN_GENCERT_BITS 1024 122*3e07920fSDavid van Moolenbroek 123*3e07920fSDavid van Moolenbroek #define SSL_CHECK_ONE(exp) do { \ 124*3e07920fSDavid van Moolenbroek if ((exp) != 1) { \ 125*3e07920fSDavid van Moolenbroek DPRINTF(D_SIGN, #exp " failed in %d: %s\n", __LINE__, \ 126*3e07920fSDavid van Moolenbroek ERR_error_string(ERR_get_error(), NULL)); \ 127*3e07920fSDavid van Moolenbroek return 1; \ 128*3e07920fSDavid van Moolenbroek } \ 129*3e07920fSDavid van Moolenbroek } while (/*CONSTCOND*/0) 130*3e07920fSDavid van Moolenbroek 131*3e07920fSDavid van Moolenbroek /* structs use uint_fast64_t in different places because the standard 132*3e07920fSDavid van Moolenbroek * requires values in interval [0:9999999999 = SIGN_MAX_COUNT] */ 133*3e07920fSDavid van Moolenbroek 134*3e07920fSDavid van Moolenbroek /* queue of C-Strings (here used for hashes) */ 135*3e07920fSDavid van Moolenbroek struct string_queue { 136*3e07920fSDavid van Moolenbroek uint_fast64_t key; 137*3e07920fSDavid van Moolenbroek char *data; 138*3e07920fSDavid van Moolenbroek STAILQ_ENTRY(string_queue) entries; 139*3e07920fSDavid van Moolenbroek }; 140*3e07920fSDavid van Moolenbroek STAILQ_HEAD(string_queue_head, string_queue); 141*3e07920fSDavid van Moolenbroek 142*3e07920fSDavid van Moolenbroek /* queue of destinations (used associate SGs and fileds) */ 143*3e07920fSDavid van Moolenbroek struct filed_queue { 144*3e07920fSDavid van Moolenbroek struct filed *f; 145*3e07920fSDavid van Moolenbroek STAILQ_ENTRY(filed_queue) entries; 146*3e07920fSDavid van Moolenbroek }; 147*3e07920fSDavid van Moolenbroek STAILQ_HEAD(filed_queue_head, filed_queue); 148*3e07920fSDavid van Moolenbroek 149*3e07920fSDavid van Moolenbroek /* queue of Signature Groups */ 150*3e07920fSDavid van Moolenbroek struct signature_group_t { 151*3e07920fSDavid van Moolenbroek unsigned spri; 152*3e07920fSDavid van Moolenbroek unsigned resendcount; 153*3e07920fSDavid van Moolenbroek uint_fast64_t last_msg_num; 154*3e07920fSDavid van Moolenbroek struct string_queue_head hashes; 155*3e07920fSDavid van Moolenbroek struct filed_queue_head files; 156*3e07920fSDavid van Moolenbroek STAILQ_ENTRY(signature_group_t) entries; 157*3e07920fSDavid van Moolenbroek }; 158*3e07920fSDavid van Moolenbroek STAILQ_HEAD(signature_group_head, signature_group_t); 159*3e07920fSDavid van Moolenbroek 160*3e07920fSDavid van Moolenbroek /* all global variables for sign */ 161*3e07920fSDavid van Moolenbroek /* note that there is one object of this type which might only be 162*3e07920fSDavid van Moolenbroek * partially filled. 163*3e07920fSDavid van Moolenbroek * The fields .sg and .sig2_delims are set by init() and are always 164*3e07920fSDavid van Moolenbroek * valid. A value >0 in field .rsid indicates whether the rest of the 165*3e07920fSDavid van Moolenbroek * structure was already set by sign_global_init(). 166*3e07920fSDavid van Moolenbroek */ 167*3e07920fSDavid van Moolenbroek struct sign_global_t { 168*3e07920fSDavid van Moolenbroek /* params for signature block, named as in RFC nnnn */ 169*3e07920fSDavid van Moolenbroek const char *ver; 170*3e07920fSDavid van Moolenbroek uint_fast64_t rsid; 171*3e07920fSDavid van Moolenbroek int sg; 172*3e07920fSDavid van Moolenbroek uint_fast64_t gbc; 173*3e07920fSDavid van Moolenbroek struct signature_group_head SigGroups; 174*3e07920fSDavid van Moolenbroek struct string_queue_head sig2_delims; 175*3e07920fSDavid van Moolenbroek 176*3e07920fSDavid van Moolenbroek EVP_PKEY *privkey; 177*3e07920fSDavid van Moolenbroek EVP_PKEY *pubkey; 178*3e07920fSDavid van Moolenbroek char *pubkey_b64; 179*3e07920fSDavid van Moolenbroek char keytype; 180*3e07920fSDavid van Moolenbroek 181*3e07920fSDavid van Moolenbroek EVP_MD_CTX *mdctx; /* hashing context */ 182*3e07920fSDavid van Moolenbroek const EVP_MD *md; /* hashing method/algorithm */ 183*3e07920fSDavid van Moolenbroek unsigned md_len_b64; /* length of b64 hash value */ 184*3e07920fSDavid van Moolenbroek 185*3e07920fSDavid van Moolenbroek EVP_MD_CTX *sigctx; /* signature context */ 186*3e07920fSDavid van Moolenbroek const EVP_MD *sig; /* signature method/algorithm */ 187*3e07920fSDavid van Moolenbroek unsigned sig_len_b64; /* length of b64 signature */ 188*3e07920fSDavid van Moolenbroek }; 189*3e07920fSDavid van Moolenbroek 190*3e07920fSDavid van Moolenbroek bool sign_global_init(struct filed*); 191*3e07920fSDavid van Moolenbroek bool sign_sg_init(struct filed*); 192*3e07920fSDavid van Moolenbroek bool sign_get_keys(void); 193*3e07920fSDavid van Moolenbroek void sign_global_free(void); 194*3e07920fSDavid van Moolenbroek struct signature_group_t* sign_get_sg(int, struct filed*); 195*3e07920fSDavid van Moolenbroek bool sign_send_certificate_block(struct signature_group_t*); 196*3e07920fSDavid van Moolenbroek unsigned sign_send_signature_block(struct signature_group_t*, bool); 197*3e07920fSDavid van Moolenbroek void sign_free_hashes(struct signature_group_t*); 198*3e07920fSDavid van Moolenbroek void sign_free_string_queue(struct string_queue_head*); 199*3e07920fSDavid van Moolenbroek bool sign_msg_hash(char*, char**); 200*3e07920fSDavid van Moolenbroek bool sign_append_hash(char*, struct signature_group_t*); 201*3e07920fSDavid van Moolenbroek bool sign_msg_sign(struct buf_msg**, char*, size_t); 202*3e07920fSDavid van Moolenbroek bool sign_string_sign(char*, char**); 203*3e07920fSDavid van Moolenbroek void sign_new_reboot_session(void); 204*3e07920fSDavid van Moolenbroek void sign_inc_gbc(void); 205*3e07920fSDavid van Moolenbroek uint_fast64_t sign_assign_msg_num(struct signature_group_t*); 206*3e07920fSDavid van Moolenbroek 207*3e07920fSDavid van Moolenbroek #endif /* SIGN_H_ */ 208