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