1*6f4965e0Srillig /* $NetBSD: sign.h,v 1.3 2021/11/27 22:30:26 rillig Exp $ */ 21c6aec20Schristos 31c6aec20Schristos /*- 41c6aec20Schristos * Copyright (c) 2008 The NetBSD Foundation, Inc. 51c6aec20Schristos * All rights reserved. 61c6aec20Schristos * 71c6aec20Schristos * This code is derived from software contributed to The NetBSD Foundation 81c6aec20Schristos * by Martin Sch�tte. 91c6aec20Schristos * 101c6aec20Schristos * Redistribution and use in source and binary forms, with or without 111c6aec20Schristos * modification, are permitted provided that the following conditions 121c6aec20Schristos * are met: 131c6aec20Schristos * 1. Redistributions of source code must retain the above copyright 141c6aec20Schristos * notice, this list of conditions and the following disclaimer. 151c6aec20Schristos * 2. Redistributions in binary form must reproduce the above copyright 161c6aec20Schristos * notice, this list of conditions and the following disclaimer in the 171c6aec20Schristos * documentation and/or other materials provided with the distribution. 181c6aec20Schristos * 3. All advertising materials mentioning features or use of this software 191c6aec20Schristos * must display the following acknowledgement: 201c6aec20Schristos * This product includes software developed by the NetBSD 211c6aec20Schristos * Foundation, Inc. and its contributors. 221c6aec20Schristos * 4. Neither the name of The NetBSD Foundation nor the names of its 231c6aec20Schristos * contributors may be used to endorse or promote products derived 241c6aec20Schristos * from this software without specific prior written permission. 251c6aec20Schristos * 261c6aec20Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 271c6aec20Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 281c6aec20Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 291c6aec20Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 301c6aec20Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 311c6aec20Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 321c6aec20Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 331c6aec20Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 341c6aec20Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 351c6aec20Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 361c6aec20Schristos * POSSIBILITY OF SUCH DAMAGE. 371c6aec20Schristos */ 381c6aec20Schristos /* 391c6aec20Schristos * sign.h 401c6aec20Schristos * 411c6aec20Schristos */ 421c6aec20Schristos #ifndef SIGN_H_ 431c6aec20Schristos #define SIGN_H_ 441c6aec20Schristos 451c6aec20Schristos #include <netinet/in.h> 461c6aec20Schristos #include <resolv.h> 471c6aec20Schristos #include <openssl/x509v3.h> 481c6aec20Schristos #include <openssl/err.h> 491c6aec20Schristos #include <openssl/rand.h> 501c6aec20Schristos #include <openssl/pem.h> 511c6aec20Schristos 521c6aec20Schristos /* default Signature Group value, 531c6aec20Schristos * defines signature strategy: 541c6aec20Schristos * 0 one global SG 551c6aec20Schristos * 1 one SG per PRI 561c6aec20Schristos * 2 SGs for PRI ranges 571c6aec20Schristos * 3 other (SGs not defined by PRI) 581c6aec20Schristos * 591c6aec20Schristos * We use '3' and assign one SG to every destination (=struct filed) 601c6aec20Schristos */ 611c6aec20Schristos #define SIGN_SG 3 621c6aec20Schristos 631c6aec20Schristos /* maximum value for several counters in -sign */ 641c6aec20Schristos #define SIGN_MAX_COUNT 9999999999 651c6aec20Schristos 661c6aec20Schristos /* 671c6aec20Schristos * many of these options could be made user configurable if desired, 681c6aec20Schristos * but I do not see the need for that 691c6aec20Schristos */ 701c6aec20Schristos 711c6aec20Schristos /* redundancy options */ 721c6aec20Schristos /* 731c6aec20Schristos * note on the implementation of redundancy: 741c6aec20Schristos * - certificate blocks: sending the first CB just before first SB. 751c6aec20Schristos * after that domark() triggers resends until resend count is reached. 761c6aec20Schristos * - signature blocks: to send every hash n times I use a sliding window. 771c6aec20Schristos * the hashes in every SB are grouped into n divisions: 781c6aec20Schristos * * the 1st hashcount/n hashes are sent for the 1st time 791c6aec20Schristos * * the 2nd hashcount/n hashes are sent for the 2nd time 801c6aec20Schristos * * ... 811c6aec20Schristos * * the n-th hashcount/n hashes are sent for the n-th time 821c6aec20Schristos * (and deleted thereafter) 831c6aec20Schristos */ 841c6aec20Schristos #define SIGN_RESENDCOUNT_CERTBLOCK 2 851c6aec20Schristos #define SIGN_RESENDCOUNT_HASHES 3 861c6aec20Schristos 871c6aec20Schristos /* maximum length of syslog-sign messages should be <= 2048 by standard 881c6aec20Schristos * and should be >= 1024 to be long enough. 891c6aec20Schristos * be careful with small values because there is no check for a lower bound 901c6aec20Schristos * thus the following derived values would become negative. 911c6aec20Schristos */ 921c6aec20Schristos #define SIGN_MAX_LENGTH 2048 931c6aec20Schristos /* the length we can use for the SD and keep the 941c6aec20Schristos * message length with header below 2048 octets */ 951c6aec20Schristos #define SIGN_MAX_SD_LENGTH (SIGN_MAX_LENGTH - 1 - HEADER_LEN_MAX) 961c6aec20Schristos /* length of signature, currently only for DSA */ 971c6aec20Schristos #define SIGN_B64SIGLEN_DSS 64+1 981c6aec20Schristos /* the maximum length of one payload fragment: 991c6aec20Schristos * max.SD len - text - max. field lengths - sig len */ 1001c6aec20Schristos #define SIGN_MAX_FRAG_LENGTH (SIGN_MAX_SD_LENGTH - 82 - 38 - SIGN_B64SIGLEN_DSS) 1011c6aec20Schristos /* the maximum length of one signature block: 1021c6aec20Schristos * max.SD len - text - max. field lens - sig len */ 1031c6aec20Schristos #define SIGN_MAX_SB_LENGTH (SIGN_MAX_SD_LENGTH - 72 - 40 - SIGN_B64SIGLEN_DSS) 1041c6aec20Schristos /* the maximum number of hashes pec signature block */ 1051c6aec20Schristos #define SIGN_MAX_HASH_NUM (SIGN_MAX_SB_LENGTH / (GlobalSign.md_len_b64+1)) 1061c6aec20Schristos /* number of hashes in one signature block */ 1071c6aec20Schristos #define SIGN_HASH_NUM_WANT 100 1081c6aec20Schristos /* make sure to consider SIGN_MAX_HASH_NUM and 1091c6aec20Schristos * to have a SIGN_HASH_NUM that is a multiple of SIGN_HASH_DIVISION_NUM */ 1101c6aec20Schristos #define SIGN_HASH_DIVISION_NUM (MIN(SIGN_HASH_NUM_WANT, SIGN_MAX_HASH_NUM) \ 1111c6aec20Schristos / SIGN_RESENDCOUNT_HASHES) 1121c6aec20Schristos #define SIGN_HASH_NUM (SIGN_HASH_DIVISION_NUM * SIGN_RESENDCOUNT_HASHES) 1131c6aec20Schristos 1141c6aec20Schristos /* the length of payload strings 1151c6aec20Schristos * since the payload is fragmented there is no technical limit 1161c6aec20Schristos * it just has to be big enough to hold big b64 encoded PKIX certificates 1171c6aec20Schristos */ 1181c6aec20Schristos #define SIGN_MAX_PAYLOAD_LENGTH 20480 1191c6aec20Schristos 1201c6aec20Schristos /* length of generated DSA keys for signing */ 1211c6aec20Schristos #define SIGN_GENCERT_BITS 1024 1221c6aec20Schristos 1231c6aec20Schristos #define SSL_CHECK_ONE(exp) do { \ 1241c6aec20Schristos if ((exp) != 1) { \ 1251c6aec20Schristos DPRINTF(D_SIGN, #exp " failed in %d: %s\n", __LINE__, \ 1261c6aec20Schristos ERR_error_string(ERR_get_error(), NULL)); \ 1271c6aec20Schristos return 1; \ 1281c6aec20Schristos } \ 129*6f4965e0Srillig } while (0) 1301c6aec20Schristos 1311c6aec20Schristos /* structs use uint_fast64_t in different places because the standard 1321c6aec20Schristos * requires values in interval [0:9999999999 = SIGN_MAX_COUNT] */ 1331c6aec20Schristos 1341c6aec20Schristos /* queue of C-Strings (here used for hashes) */ 1351c6aec20Schristos struct string_queue { 1361c6aec20Schristos uint_fast64_t key; 1371c6aec20Schristos char *data; 1381c6aec20Schristos STAILQ_ENTRY(string_queue) entries; 1391c6aec20Schristos }; 1401c6aec20Schristos STAILQ_HEAD(string_queue_head, string_queue); 1411c6aec20Schristos 1421c6aec20Schristos /* queue of destinations (used associate SGs and fileds) */ 1431c6aec20Schristos struct filed_queue { 1441c6aec20Schristos struct filed *f; 1451c6aec20Schristos STAILQ_ENTRY(filed_queue) entries; 1461c6aec20Schristos }; 1471c6aec20Schristos STAILQ_HEAD(filed_queue_head, filed_queue); 1481c6aec20Schristos 1491c6aec20Schristos /* queue of Signature Groups */ 1501c6aec20Schristos struct signature_group_t { 1511c6aec20Schristos unsigned spri; 1521c6aec20Schristos unsigned resendcount; 1531c6aec20Schristos uint_fast64_t last_msg_num; 1541c6aec20Schristos struct string_queue_head hashes; 1551c6aec20Schristos struct filed_queue_head files; 1561c6aec20Schristos STAILQ_ENTRY(signature_group_t) entries; 1571c6aec20Schristos }; 1581c6aec20Schristos STAILQ_HEAD(signature_group_head, signature_group_t); 1591c6aec20Schristos 1601c6aec20Schristos /* all global variables for sign */ 1611c6aec20Schristos /* note that there is one object of this type which might only be 1621c6aec20Schristos * partially filled. 1631c6aec20Schristos * The fields .sg and .sig2_delims are set by init() and are always 1641c6aec20Schristos * valid. A value >0 in field .rsid indicates whether the rest of the 1651c6aec20Schristos * structure was already set by sign_global_init(). 1661c6aec20Schristos */ 1671c6aec20Schristos struct sign_global_t { 1681c6aec20Schristos /* params for signature block, named as in RFC nnnn */ 1691c6aec20Schristos const char *ver; 1701c6aec20Schristos uint_fast64_t rsid; 1711c6aec20Schristos int sg; 1721c6aec20Schristos uint_fast64_t gbc; 1731c6aec20Schristos struct signature_group_head SigGroups; 1741c6aec20Schristos struct string_queue_head sig2_delims; 1751c6aec20Schristos 1761c6aec20Schristos EVP_PKEY *privkey; 1771c6aec20Schristos EVP_PKEY *pubkey; 1781c6aec20Schristos char *pubkey_b64; 1791c6aec20Schristos char keytype; 1801c6aec20Schristos 1811c6aec20Schristos EVP_MD_CTX *mdctx; /* hashing context */ 1821c6aec20Schristos const EVP_MD *md; /* hashing method/algorithm */ 1831c6aec20Schristos unsigned md_len_b64; /* length of b64 hash value */ 1841c6aec20Schristos 1851c6aec20Schristos EVP_MD_CTX *sigctx; /* signature context */ 1861c6aec20Schristos const EVP_MD *sig; /* signature method/algorithm */ 1871c6aec20Schristos unsigned sig_len_b64; /* length of b64 signature */ 1881c6aec20Schristos }; 1891c6aec20Schristos 1901c6aec20Schristos bool sign_global_init(struct filed*); 1911c6aec20Schristos bool sign_sg_init(struct filed*); 1921c6aec20Schristos bool sign_get_keys(void); 1931c6aec20Schristos void sign_global_free(void); 1941c6aec20Schristos struct signature_group_t* sign_get_sg(int, struct filed*); 1951c6aec20Schristos bool sign_send_certificate_block(struct signature_group_t*); 1961c6aec20Schristos unsigned sign_send_signature_block(struct signature_group_t*, bool); 1971c6aec20Schristos void sign_free_hashes(struct signature_group_t*); 1981c6aec20Schristos void sign_free_string_queue(struct string_queue_head*); 1991c6aec20Schristos bool sign_msg_hash(char*, char**); 2001c6aec20Schristos bool sign_append_hash(char*, struct signature_group_t*); 2011c6aec20Schristos bool sign_msg_sign(struct buf_msg**, char*, size_t); 2021c6aec20Schristos bool sign_string_sign(char*, char**); 2031c6aec20Schristos void sign_new_reboot_session(void); 2041c6aec20Schristos void sign_inc_gbc(void); 2051c6aec20Schristos uint_fast64_t sign_assign_msg_num(struct signature_group_t*); 2061c6aec20Schristos 2071c6aec20Schristos #endif /* SIGN_H_ */ 208