1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gate /* 9*7c478bd9Sstevel@tonic-gate * Copyright (c) 1999 by Internet Software Consortium, Inc. 10*7c478bd9Sstevel@tonic-gate * 11*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 12*7c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 13*7c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 14*7c478bd9Sstevel@tonic-gate * 15*7c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 16*7c478bd9Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 17*7c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 18*7c478bd9Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 19*7c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 20*7c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 21*7c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 22*7c478bd9Sstevel@tonic-gate * SOFTWARE. 23*7c478bd9Sstevel@tonic-gate */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate #ifndef lint 26*7c478bd9Sstevel@tonic-gate static const char rcsid[] = "$Id: ns_sign.c,v 8.12 2002/10/01 06:48:37 marka Exp $"; 27*7c478bd9Sstevel@tonic-gate #endif 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Import. */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include "port_before.h" 32*7c478bd9Sstevel@tonic-gate #include "fd_setsize.h" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 38*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 39*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #include <errno.h> 42*7c478bd9Sstevel@tonic-gate #include <netdb.h> 43*7c478bd9Sstevel@tonic-gate #include <resolv.h> 44*7c478bd9Sstevel@tonic-gate #include <stdio.h> 45*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 46*7c478bd9Sstevel@tonic-gate #include <string.h> 47*7c478bd9Sstevel@tonic-gate #include <time.h> 48*7c478bd9Sstevel@tonic-gate #include <unistd.h> 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #include <isc/dst.h> 51*7c478bd9Sstevel@tonic-gate #include <isc/assertions.h> 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #include "port_after.h" 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define BOUNDS_CHECK(ptr, count) \ 56*7c478bd9Sstevel@tonic-gate do { \ 57*7c478bd9Sstevel@tonic-gate if ((ptr) + (count) > eob) { \ 58*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; \ 59*7c478bd9Sstevel@tonic-gate return(NS_TSIG_ERROR_NO_SPACE); \ 60*7c478bd9Sstevel@tonic-gate } \ 61*7c478bd9Sstevel@tonic-gate } while (0) 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* ns_sign 64*7c478bd9Sstevel@tonic-gate * Parameters: 65*7c478bd9Sstevel@tonic-gate * msg message to be sent 66*7c478bd9Sstevel@tonic-gate * msglen input - length of message 67*7c478bd9Sstevel@tonic-gate * output - length of signed message 68*7c478bd9Sstevel@tonic-gate * msgsize length of buffer containing message 69*7c478bd9Sstevel@tonic-gate * error value to put in the error field 70*7c478bd9Sstevel@tonic-gate * key tsig key used for signing 71*7c478bd9Sstevel@tonic-gate * querysig (response), the signature in the query 72*7c478bd9Sstevel@tonic-gate * querysiglen (response), the length of the signature in the query 73*7c478bd9Sstevel@tonic-gate * sig a buffer to hold the generated signature 74*7c478bd9Sstevel@tonic-gate * siglen input - length of signature buffer 75*7c478bd9Sstevel@tonic-gate * output - length of signature 76*7c478bd9Sstevel@tonic-gate * 77*7c478bd9Sstevel@tonic-gate * Errors: 78*7c478bd9Sstevel@tonic-gate * - bad input data (-1) 79*7c478bd9Sstevel@tonic-gate * - bad key / sign failed (-BADKEY) 80*7c478bd9Sstevel@tonic-gate * - not enough space (NS_TSIG_ERROR_NO_SPACE) 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate int 83*7c478bd9Sstevel@tonic-gate ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k, 84*7c478bd9Sstevel@tonic-gate const u_char *querysig, int querysiglen, u_char *sig, int *siglen, 85*7c478bd9Sstevel@tonic-gate time_t in_timesigned) 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate return(ns_sign2(msg, msglen, msgsize, error, k, 88*7c478bd9Sstevel@tonic-gate querysig, querysiglen, sig, siglen, 89*7c478bd9Sstevel@tonic-gate in_timesigned, NULL, NULL)); 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate int 93*7c478bd9Sstevel@tonic-gate ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k, 94*7c478bd9Sstevel@tonic-gate const u_char *querysig, int querysiglen, u_char *sig, int *siglen, 95*7c478bd9Sstevel@tonic-gate time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr) 96*7c478bd9Sstevel@tonic-gate { 97*7c478bd9Sstevel@tonic-gate HEADER *hp = (HEADER *)msg; 98*7c478bd9Sstevel@tonic-gate DST_KEY *key = (DST_KEY *)k; 99*7c478bd9Sstevel@tonic-gate u_char *cp = msg + *msglen, *eob = msg + msgsize; 100*7c478bd9Sstevel@tonic-gate u_char *lenp; 101*7c478bd9Sstevel@tonic-gate u_char *alg; 102*7c478bd9Sstevel@tonic-gate int n; 103*7c478bd9Sstevel@tonic-gate time_t timesigned; 104*7c478bd9Sstevel@tonic-gate u_char name[NS_MAXCDNAME]; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate dst_init(); 107*7c478bd9Sstevel@tonic-gate if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL) 108*7c478bd9Sstevel@tonic-gate return (-1); 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate /* Name. */ 111*7c478bd9Sstevel@tonic-gate if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { 112*7c478bd9Sstevel@tonic-gate n = ns_name_pton(key->dk_key_name, name, sizeof name); 113*7c478bd9Sstevel@tonic-gate if (n != -1) 114*7c478bd9Sstevel@tonic-gate n = ns_name_pack(name, cp, eob - cp, 115*7c478bd9Sstevel@tonic-gate (const u_char **)dnptrs, 116*7c478bd9Sstevel@tonic-gate (const u_char **)lastdnptr); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate } else { 119*7c478bd9Sstevel@tonic-gate n = ns_name_pton("", name, sizeof name); 120*7c478bd9Sstevel@tonic-gate if (n != -1) 121*7c478bd9Sstevel@tonic-gate n = ns_name_pack(name, cp, eob - cp, NULL, NULL); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate if (n < 0) 124*7c478bd9Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE); 125*7c478bd9Sstevel@tonic-gate cp += n; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* Type, class, ttl, length (not filled in yet). */ 128*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); 129*7c478bd9Sstevel@tonic-gate PUTSHORT(ns_t_tsig, cp); 130*7c478bd9Sstevel@tonic-gate PUTSHORT(ns_c_any, cp); 131*7c478bd9Sstevel@tonic-gate PUTLONG(0, cp); /* TTL */ 132*7c478bd9Sstevel@tonic-gate lenp = cp; 133*7c478bd9Sstevel@tonic-gate cp += 2; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* Alg. */ 136*7c478bd9Sstevel@tonic-gate if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { 137*7c478bd9Sstevel@tonic-gate if (key->dk_alg != KEY_HMAC_MD5) 138*7c478bd9Sstevel@tonic-gate return (-ns_r_badkey); 139*7c478bd9Sstevel@tonic-gate n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate else 142*7c478bd9Sstevel@tonic-gate n = dn_comp("", cp, eob - cp, NULL, NULL); 143*7c478bd9Sstevel@tonic-gate if (n < 0) 144*7c478bd9Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE); 145*7c478bd9Sstevel@tonic-gate alg = cp; 146*7c478bd9Sstevel@tonic-gate cp += n; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* Time. */ 149*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); 150*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp); 151*7c478bd9Sstevel@tonic-gate timesigned = time(NULL); 152*7c478bd9Sstevel@tonic-gate if (error != ns_r_badtime) 153*7c478bd9Sstevel@tonic-gate PUTLONG(timesigned, cp); 154*7c478bd9Sstevel@tonic-gate else 155*7c478bd9Sstevel@tonic-gate PUTLONG(in_timesigned, cp); 156*7c478bd9Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp); 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* Compute the signature. */ 159*7c478bd9Sstevel@tonic-gate if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { 160*7c478bd9Sstevel@tonic-gate void *ctx; 161*7c478bd9Sstevel@tonic-gate u_char buf[NS_MAXCDNAME], *cp2; 162*7c478bd9Sstevel@tonic-gate int n; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* Digest the query signature, if this is a response. */ 167*7c478bd9Sstevel@tonic-gate if (querysiglen > 0 && querysig != NULL) { 168*7c478bd9Sstevel@tonic-gate u_int16_t len_n = htons(querysiglen); 169*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, 170*7c478bd9Sstevel@tonic-gate (u_char *)&len_n, INT16SZ, NULL, 0); 171*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, 172*7c478bd9Sstevel@tonic-gate querysig, querysiglen, NULL, 0); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* Digest the message. */ 176*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen, 177*7c478bd9Sstevel@tonic-gate NULL, 0); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* Digest the key name. */ 180*7c478bd9Sstevel@tonic-gate n = ns_name_ntol(name, buf, sizeof(buf)); 181*7c478bd9Sstevel@tonic-gate INSIST(n > 0); 182*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* Digest the class and TTL. */ 185*7c478bd9Sstevel@tonic-gate cp2 = buf; 186*7c478bd9Sstevel@tonic-gate PUTSHORT(ns_c_any, cp2); 187*7c478bd9Sstevel@tonic-gate PUTLONG(0, cp2); 188*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, 189*7c478bd9Sstevel@tonic-gate NULL, 0); 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* Digest the algorithm. */ 192*7c478bd9Sstevel@tonic-gate n = ns_name_ntol(alg, buf, sizeof(buf)); 193*7c478bd9Sstevel@tonic-gate INSIST(n > 0); 194*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* Digest the time signed, fudge, error, and other data */ 197*7c478bd9Sstevel@tonic-gate cp2 = buf; 198*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp2); /* Top 16 bits of time */ 199*7c478bd9Sstevel@tonic-gate if (error != ns_r_badtime) 200*7c478bd9Sstevel@tonic-gate PUTLONG(timesigned, cp2); 201*7c478bd9Sstevel@tonic-gate else 202*7c478bd9Sstevel@tonic-gate PUTLONG(in_timesigned, cp2); 203*7c478bd9Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp2); 204*7c478bd9Sstevel@tonic-gate PUTSHORT(error, cp2); /* Error */ 205*7c478bd9Sstevel@tonic-gate if (error != ns_r_badtime) 206*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp2); /* Other data length */ 207*7c478bd9Sstevel@tonic-gate else { 208*7c478bd9Sstevel@tonic-gate PUTSHORT(INT16SZ+INT32SZ, cp2); /* Other data length */ 209*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp2); /* Top 16 bits of time */ 210*7c478bd9Sstevel@tonic-gate PUTLONG(timesigned, cp2); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, 213*7c478bd9Sstevel@tonic-gate NULL, 0); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, 216*7c478bd9Sstevel@tonic-gate sig, *siglen); 217*7c478bd9Sstevel@tonic-gate if (n < 0) 218*7c478bd9Sstevel@tonic-gate return (-ns_r_badkey); 219*7c478bd9Sstevel@tonic-gate *siglen = n; 220*7c478bd9Sstevel@tonic-gate } else 221*7c478bd9Sstevel@tonic-gate *siglen = 0; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* Add the signature. */ 224*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + (*siglen)); 225*7c478bd9Sstevel@tonic-gate PUTSHORT(*siglen, cp); 226*7c478bd9Sstevel@tonic-gate memcpy(cp, sig, *siglen); 227*7c478bd9Sstevel@tonic-gate cp += (*siglen); 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate /* The original message ID & error. */ 230*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ); 231*7c478bd9Sstevel@tonic-gate PUTSHORT(ntohs(hp->id), cp); /* already in network order */ 232*7c478bd9Sstevel@tonic-gate PUTSHORT(error, cp); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* Other data. */ 235*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ); 236*7c478bd9Sstevel@tonic-gate if (error != ns_r_badtime) 237*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp); /* Other data length */ 238*7c478bd9Sstevel@tonic-gate else { 239*7c478bd9Sstevel@tonic-gate PUTSHORT(INT16SZ+INT32SZ, cp); /* Other data length */ 240*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT32SZ+INT16SZ); 241*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp); /* Top 16 bits of time */ 242*7c478bd9Sstevel@tonic-gate PUTLONG(timesigned, cp); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* Go back and fill in the length. */ 246*7c478bd9Sstevel@tonic-gate PUTSHORT(cp - lenp - INT16SZ, lenp); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate hp->arcount = htons(ntohs(hp->arcount) + 1); 249*7c478bd9Sstevel@tonic-gate *msglen = (cp - msg); 250*7c478bd9Sstevel@tonic-gate return (0); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate int 254*7c478bd9Sstevel@tonic-gate ns_sign_tcp_init(void *k, const u_char *querysig, int querysiglen, 255*7c478bd9Sstevel@tonic-gate ns_tcp_tsig_state *state) 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate dst_init(); 258*7c478bd9Sstevel@tonic-gate if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) 259*7c478bd9Sstevel@tonic-gate return (-1); 260*7c478bd9Sstevel@tonic-gate state->counter = -1; 261*7c478bd9Sstevel@tonic-gate state->key = k; 262*7c478bd9Sstevel@tonic-gate if (state->key->dk_alg != KEY_HMAC_MD5) 263*7c478bd9Sstevel@tonic-gate return (-ns_r_badkey); 264*7c478bd9Sstevel@tonic-gate if (querysiglen > (int)sizeof(state->sig)) 265*7c478bd9Sstevel@tonic-gate return (-1); 266*7c478bd9Sstevel@tonic-gate memcpy(state->sig, querysig, querysiglen); 267*7c478bd9Sstevel@tonic-gate state->siglen = querysiglen; 268*7c478bd9Sstevel@tonic-gate return (0); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate int 272*7c478bd9Sstevel@tonic-gate ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error, 273*7c478bd9Sstevel@tonic-gate ns_tcp_tsig_state *state, int done) 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate return (ns_sign_tcp2(msg, msglen, msgsize, error, state, 276*7c478bd9Sstevel@tonic-gate done, NULL, NULL)); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate int 280*7c478bd9Sstevel@tonic-gate ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error, 281*7c478bd9Sstevel@tonic-gate ns_tcp_tsig_state *state, int done, 282*7c478bd9Sstevel@tonic-gate u_char **dnptrs, u_char **lastdnptr) 283*7c478bd9Sstevel@tonic-gate { 284*7c478bd9Sstevel@tonic-gate u_char *cp, *eob, *lenp; 285*7c478bd9Sstevel@tonic-gate u_char buf[MAXDNAME], *cp2; 286*7c478bd9Sstevel@tonic-gate HEADER *hp = (HEADER *)msg; 287*7c478bd9Sstevel@tonic-gate time_t timesigned; 288*7c478bd9Sstevel@tonic-gate int n; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate if (msg == NULL || msglen == NULL || state == NULL) 291*7c478bd9Sstevel@tonic-gate return (-1); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate state->counter++; 294*7c478bd9Sstevel@tonic-gate if (state->counter == 0) 295*7c478bd9Sstevel@tonic-gate return (ns_sign2(msg, msglen, msgsize, error, state->key, 296*7c478bd9Sstevel@tonic-gate state->sig, state->siglen, 297*7c478bd9Sstevel@tonic-gate state->sig, &state->siglen, 0, 298*7c478bd9Sstevel@tonic-gate dnptrs, lastdnptr)); 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate if (state->siglen > 0) { 301*7c478bd9Sstevel@tonic-gate u_int16_t siglen_n = htons(state->siglen); 302*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx, 303*7c478bd9Sstevel@tonic-gate NULL, 0, NULL, 0); 304*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, 305*7c478bd9Sstevel@tonic-gate (u_char *)&siglen_n, INT16SZ, NULL, 0); 306*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, 307*7c478bd9Sstevel@tonic-gate state->sig, state->siglen, NULL, 0); 308*7c478bd9Sstevel@tonic-gate state->siglen = 0; 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen, 312*7c478bd9Sstevel@tonic-gate NULL, 0); 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate if (done == 0 && (state->counter % 100 != 0)) 315*7c478bd9Sstevel@tonic-gate return (0); 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate cp = msg + *msglen; 318*7c478bd9Sstevel@tonic-gate eob = msg + msgsize; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* Name. */ 321*7c478bd9Sstevel@tonic-gate n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr); 322*7c478bd9Sstevel@tonic-gate if (n < 0) 323*7c478bd9Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE); 324*7c478bd9Sstevel@tonic-gate cp += n; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* Type, class, ttl, length (not filled in yet). */ 327*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); 328*7c478bd9Sstevel@tonic-gate PUTSHORT(ns_t_tsig, cp); 329*7c478bd9Sstevel@tonic-gate PUTSHORT(ns_c_any, cp); 330*7c478bd9Sstevel@tonic-gate PUTLONG(0, cp); /* TTL */ 331*7c478bd9Sstevel@tonic-gate lenp = cp; 332*7c478bd9Sstevel@tonic-gate cp += 2; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* Alg. */ 335*7c478bd9Sstevel@tonic-gate n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); 336*7c478bd9Sstevel@tonic-gate if (n < 0) 337*7c478bd9Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE); 338*7c478bd9Sstevel@tonic-gate cp += n; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* Time. */ 341*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); 342*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp); 343*7c478bd9Sstevel@tonic-gate timesigned = time(NULL); 344*7c478bd9Sstevel@tonic-gate PUTLONG(timesigned, cp); 345*7c478bd9Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Compute the signature. 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* Digest the time signed and fudge. */ 352*7c478bd9Sstevel@tonic-gate cp2 = buf; 353*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp2); /* Top 16 bits of time */ 354*7c478bd9Sstevel@tonic-gate PUTLONG(timesigned, cp2); 355*7c478bd9Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp2); 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, 358*7c478bd9Sstevel@tonic-gate buf, cp2 - buf, NULL, 0); 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, 361*7c478bd9Sstevel@tonic-gate state->sig, sizeof(state->sig)); 362*7c478bd9Sstevel@tonic-gate if (n < 0) 363*7c478bd9Sstevel@tonic-gate return (-ns_r_badkey); 364*7c478bd9Sstevel@tonic-gate state->siglen = n; 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* Add the signature. */ 367*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + state->siglen); 368*7c478bd9Sstevel@tonic-gate PUTSHORT(state->siglen, cp); 369*7c478bd9Sstevel@tonic-gate memcpy(cp, state->sig, state->siglen); 370*7c478bd9Sstevel@tonic-gate cp += state->siglen; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /* The original message ID & error. */ 373*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ); 374*7c478bd9Sstevel@tonic-gate PUTSHORT(ntohs(hp->id), cp); /* already in network order */ 375*7c478bd9Sstevel@tonic-gate PUTSHORT(error, cp); 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate /* Other data. */ 378*7c478bd9Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ); 379*7c478bd9Sstevel@tonic-gate PUTSHORT(0, cp); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* Go back and fill in the length. */ 382*7c478bd9Sstevel@tonic-gate PUTSHORT(cp - lenp - INT16SZ, lenp); 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate hp->arcount = htons(ntohs(hp->arcount) + 1); 385*7c478bd9Sstevel@tonic-gate *msglen = (cp - msg); 386*7c478bd9Sstevel@tonic-gate return (0); 387*7c478bd9Sstevel@tonic-gate } 388