10Sstevel@tonic-gate /*
2*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
30Sstevel@tonic-gate * Copyright (c) 1999 by Internet Software Consortium, Inc.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any
60Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
70Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
80Sstevel@tonic-gate *
9*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
160Sstevel@tonic-gate */
170Sstevel@tonic-gate
180Sstevel@tonic-gate #ifndef lint
19*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: ns_sign.c,v 1.6 2006/03/09 23:57:56 marka Exp $";
200Sstevel@tonic-gate #endif
210Sstevel@tonic-gate
220Sstevel@tonic-gate /* Import. */
230Sstevel@tonic-gate
240Sstevel@tonic-gate #include "port_before.h"
250Sstevel@tonic-gate #include "fd_setsize.h"
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/param.h>
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <netinet/in.h>
310Sstevel@tonic-gate #include <arpa/nameser.h>
320Sstevel@tonic-gate #include <arpa/inet.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include <netdb.h>
360Sstevel@tonic-gate #include <resolv.h>
370Sstevel@tonic-gate #include <stdio.h>
380Sstevel@tonic-gate #include <stdlib.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <time.h>
410Sstevel@tonic-gate #include <unistd.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include <isc/dst.h>
440Sstevel@tonic-gate #include <isc/assertions.h>
450Sstevel@tonic-gate
460Sstevel@tonic-gate #include "port_after.h"
470Sstevel@tonic-gate
480Sstevel@tonic-gate #define BOUNDS_CHECK(ptr, count) \
490Sstevel@tonic-gate do { \
500Sstevel@tonic-gate if ((ptr) + (count) > eob) { \
510Sstevel@tonic-gate errno = EMSGSIZE; \
520Sstevel@tonic-gate return(NS_TSIG_ERROR_NO_SPACE); \
530Sstevel@tonic-gate } \
540Sstevel@tonic-gate } while (0)
550Sstevel@tonic-gate
56*11038SRao.Shoaib@Sun.COM /*%
57*11038SRao.Shoaib@Sun.COM * ns_sign
58*11038SRao.Shoaib@Sun.COM *
590Sstevel@tonic-gate * Parameters:
60*11038SRao.Shoaib@Sun.COM *\li msg message to be sent
61*11038SRao.Shoaib@Sun.COM *\li msglen input - length of message
620Sstevel@tonic-gate * output - length of signed message
63*11038SRao.Shoaib@Sun.COM *\li msgsize length of buffer containing message
64*11038SRao.Shoaib@Sun.COM *\li error value to put in the error field
65*11038SRao.Shoaib@Sun.COM *\li key tsig key used for signing
66*11038SRao.Shoaib@Sun.COM *\li querysig (response), the signature in the query
67*11038SRao.Shoaib@Sun.COM *\li querysiglen (response), the length of the signature in the query
68*11038SRao.Shoaib@Sun.COM *\li sig a buffer to hold the generated signature
69*11038SRao.Shoaib@Sun.COM *\li siglen input - length of signature buffer
700Sstevel@tonic-gate * output - length of signature
710Sstevel@tonic-gate *
720Sstevel@tonic-gate * Errors:
73*11038SRao.Shoaib@Sun.COM *\li - bad input data (-1)
74*11038SRao.Shoaib@Sun.COM *\li - bad key / sign failed (-BADKEY)
75*11038SRao.Shoaib@Sun.COM *\li - not enough space (NS_TSIG_ERROR_NO_SPACE)
760Sstevel@tonic-gate */
770Sstevel@tonic-gate int
ns_sign(u_char * msg,int * msglen,int msgsize,int error,void * k,const u_char * querysig,int querysiglen,u_char * sig,int * siglen,time_t in_timesigned)780Sstevel@tonic-gate ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k,
790Sstevel@tonic-gate const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
800Sstevel@tonic-gate time_t in_timesigned)
810Sstevel@tonic-gate {
820Sstevel@tonic-gate return(ns_sign2(msg, msglen, msgsize, error, k,
830Sstevel@tonic-gate querysig, querysiglen, sig, siglen,
840Sstevel@tonic-gate in_timesigned, NULL, NULL));
850Sstevel@tonic-gate }
860Sstevel@tonic-gate
870Sstevel@tonic-gate int
ns_sign2(u_char * msg,int * msglen,int msgsize,int error,void * k,const u_char * querysig,int querysiglen,u_char * sig,int * siglen,time_t in_timesigned,u_char ** dnptrs,u_char ** lastdnptr)880Sstevel@tonic-gate ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k,
890Sstevel@tonic-gate const u_char *querysig, int querysiglen, u_char *sig, int *siglen,
900Sstevel@tonic-gate time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate HEADER *hp = (HEADER *)msg;
930Sstevel@tonic-gate DST_KEY *key = (DST_KEY *)k;
94*11038SRao.Shoaib@Sun.COM u_char *cp, *eob;
950Sstevel@tonic-gate u_char *lenp;
960Sstevel@tonic-gate u_char *alg;
970Sstevel@tonic-gate int n;
980Sstevel@tonic-gate time_t timesigned;
99*11038SRao.Shoaib@Sun.COM u_char name[NS_MAXCDNAME];
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate dst_init();
1020Sstevel@tonic-gate if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL)
1030Sstevel@tonic-gate return (-1);
1040Sstevel@tonic-gate
105*11038SRao.Shoaib@Sun.COM cp = msg + *msglen;
106*11038SRao.Shoaib@Sun.COM eob = msg + msgsize;
107*11038SRao.Shoaib@Sun.COM
1080Sstevel@tonic-gate /* Name. */
1090Sstevel@tonic-gate if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
1100Sstevel@tonic-gate n = ns_name_pton(key->dk_key_name, name, sizeof name);
1110Sstevel@tonic-gate if (n != -1)
1120Sstevel@tonic-gate n = ns_name_pack(name, cp, eob - cp,
113*11038SRao.Shoaib@Sun.COM (const u_char **)dnptrs,
114*11038SRao.Shoaib@Sun.COM (const u_char **)lastdnptr);
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate } else {
1170Sstevel@tonic-gate n = ns_name_pton("", name, sizeof name);
1180Sstevel@tonic-gate if (n != -1)
1190Sstevel@tonic-gate n = ns_name_pack(name, cp, eob - cp, NULL, NULL);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate if (n < 0)
1220Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE);
1230Sstevel@tonic-gate cp += n;
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /* Type, class, ttl, length (not filled in yet). */
1260Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
1270Sstevel@tonic-gate PUTSHORT(ns_t_tsig, cp);
1280Sstevel@tonic-gate PUTSHORT(ns_c_any, cp);
129*11038SRao.Shoaib@Sun.COM PUTLONG(0, cp); /*%< TTL */
1300Sstevel@tonic-gate lenp = cp;
1310Sstevel@tonic-gate cp += 2;
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /* Alg. */
1340Sstevel@tonic-gate if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
1350Sstevel@tonic-gate if (key->dk_alg != KEY_HMAC_MD5)
1360Sstevel@tonic-gate return (-ns_r_badkey);
1370Sstevel@tonic-gate n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate else
1400Sstevel@tonic-gate n = dn_comp("", cp, eob - cp, NULL, NULL);
1410Sstevel@tonic-gate if (n < 0)
1420Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE);
1430Sstevel@tonic-gate alg = cp;
1440Sstevel@tonic-gate cp += n;
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate /* Time. */
1470Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
1480Sstevel@tonic-gate PUTSHORT(0, cp);
1490Sstevel@tonic-gate timesigned = time(NULL);
1500Sstevel@tonic-gate if (error != ns_r_badtime)
1510Sstevel@tonic-gate PUTLONG(timesigned, cp);
1520Sstevel@tonic-gate else
1530Sstevel@tonic-gate PUTLONG(in_timesigned, cp);
1540Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp);
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate /* Compute the signature. */
1570Sstevel@tonic-gate if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
1580Sstevel@tonic-gate void *ctx;
1590Sstevel@tonic-gate u_char buf[NS_MAXCDNAME], *cp2;
1600Sstevel@tonic-gate int n;
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0);
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /* Digest the query signature, if this is a response. */
1650Sstevel@tonic-gate if (querysiglen > 0 && querysig != NULL) {
1660Sstevel@tonic-gate u_int16_t len_n = htons(querysiglen);
1670Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
1680Sstevel@tonic-gate (u_char *)&len_n, INT16SZ, NULL, 0);
1690Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx,
1700Sstevel@tonic-gate querysig, querysiglen, NULL, 0);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate /* Digest the message. */
1740Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen,
1750Sstevel@tonic-gate NULL, 0);
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate /* Digest the key name. */
1780Sstevel@tonic-gate n = ns_name_ntol(name, buf, sizeof(buf));
1790Sstevel@tonic-gate INSIST(n > 0);
1800Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /* Digest the class and TTL. */
1830Sstevel@tonic-gate cp2 = buf;
1840Sstevel@tonic-gate PUTSHORT(ns_c_any, cp2);
1850Sstevel@tonic-gate PUTLONG(0, cp2);
1860Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
1870Sstevel@tonic-gate NULL, 0);
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate /* Digest the algorithm. */
1900Sstevel@tonic-gate n = ns_name_ntol(alg, buf, sizeof(buf));
1910Sstevel@tonic-gate INSIST(n > 0);
1920Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate /* Digest the time signed, fudge, error, and other data */
1950Sstevel@tonic-gate cp2 = buf;
196*11038SRao.Shoaib@Sun.COM PUTSHORT(0, cp2); /*%< Top 16 bits of time */
1970Sstevel@tonic-gate if (error != ns_r_badtime)
1980Sstevel@tonic-gate PUTLONG(timesigned, cp2);
1990Sstevel@tonic-gate else
2000Sstevel@tonic-gate PUTLONG(in_timesigned, cp2);
2010Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp2);
202*11038SRao.Shoaib@Sun.COM PUTSHORT(error, cp2); /*%< Error */
2030Sstevel@tonic-gate if (error != ns_r_badtime)
204*11038SRao.Shoaib@Sun.COM PUTSHORT(0, cp2); /*%< Other data length */
2050Sstevel@tonic-gate else {
206*11038SRao.Shoaib@Sun.COM PUTSHORT(INT16SZ+INT32SZ, cp2); /*%< Other data length */
207*11038SRao.Shoaib@Sun.COM PUTSHORT(0, cp2); /*%< Top 16 bits of time */
2080Sstevel@tonic-gate PUTLONG(timesigned, cp2);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf,
2110Sstevel@tonic-gate NULL, 0);
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
2140Sstevel@tonic-gate sig, *siglen);
2150Sstevel@tonic-gate if (n < 0)
2160Sstevel@tonic-gate return (-ns_r_badkey);
2170Sstevel@tonic-gate *siglen = n;
2180Sstevel@tonic-gate } else
2190Sstevel@tonic-gate *siglen = 0;
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /* Add the signature. */
2220Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + (*siglen));
2230Sstevel@tonic-gate PUTSHORT(*siglen, cp);
2240Sstevel@tonic-gate memcpy(cp, sig, *siglen);
2250Sstevel@tonic-gate cp += (*siglen);
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate /* The original message ID & error. */
2280Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
229*11038SRao.Shoaib@Sun.COM PUTSHORT(ntohs(hp->id), cp); /*%< already in network order */
2300Sstevel@tonic-gate PUTSHORT(error, cp);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate /* Other data. */
2330Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ);
2340Sstevel@tonic-gate if (error != ns_r_badtime)
235*11038SRao.Shoaib@Sun.COM PUTSHORT(0, cp); /*%< Other data length */
2360Sstevel@tonic-gate else {
237*11038SRao.Shoaib@Sun.COM PUTSHORT(INT16SZ+INT32SZ, cp); /*%< Other data length */
2380Sstevel@tonic-gate BOUNDS_CHECK(cp, INT32SZ+INT16SZ);
239*11038SRao.Shoaib@Sun.COM PUTSHORT(0, cp); /*%< Top 16 bits of time */
2400Sstevel@tonic-gate PUTLONG(timesigned, cp);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate /* Go back and fill in the length. */
2440Sstevel@tonic-gate PUTSHORT(cp - lenp - INT16SZ, lenp);
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate hp->arcount = htons(ntohs(hp->arcount) + 1);
2470Sstevel@tonic-gate *msglen = (cp - msg);
2480Sstevel@tonic-gate return (0);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate int
ns_sign_tcp_init(void * k,const u_char * querysig,int querysiglen,ns_tcp_tsig_state * state)2520Sstevel@tonic-gate ns_sign_tcp_init(void *k, const u_char *querysig, int querysiglen,
2530Sstevel@tonic-gate ns_tcp_tsig_state *state)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate dst_init();
2560Sstevel@tonic-gate if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0)
2570Sstevel@tonic-gate return (-1);
2580Sstevel@tonic-gate state->counter = -1;
2590Sstevel@tonic-gate state->key = k;
2600Sstevel@tonic-gate if (state->key->dk_alg != KEY_HMAC_MD5)
2610Sstevel@tonic-gate return (-ns_r_badkey);
2620Sstevel@tonic-gate if (querysiglen > (int)sizeof(state->sig))
2630Sstevel@tonic-gate return (-1);
2640Sstevel@tonic-gate memcpy(state->sig, querysig, querysiglen);
2650Sstevel@tonic-gate state->siglen = querysiglen;
2660Sstevel@tonic-gate return (0);
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate int
ns_sign_tcp(u_char * msg,int * msglen,int msgsize,int error,ns_tcp_tsig_state * state,int done)2700Sstevel@tonic-gate ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error,
2710Sstevel@tonic-gate ns_tcp_tsig_state *state, int done)
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate return (ns_sign_tcp2(msg, msglen, msgsize, error, state,
2740Sstevel@tonic-gate done, NULL, NULL));
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate int
ns_sign_tcp2(u_char * msg,int * msglen,int msgsize,int error,ns_tcp_tsig_state * state,int done,u_char ** dnptrs,u_char ** lastdnptr)2780Sstevel@tonic-gate ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error,
2790Sstevel@tonic-gate ns_tcp_tsig_state *state, int done,
2800Sstevel@tonic-gate u_char **dnptrs, u_char **lastdnptr)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate u_char *cp, *eob, *lenp;
2830Sstevel@tonic-gate u_char buf[MAXDNAME], *cp2;
2840Sstevel@tonic-gate HEADER *hp = (HEADER *)msg;
2850Sstevel@tonic-gate time_t timesigned;
2860Sstevel@tonic-gate int n;
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate if (msg == NULL || msglen == NULL || state == NULL)
2890Sstevel@tonic-gate return (-1);
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate state->counter++;
2920Sstevel@tonic-gate if (state->counter == 0)
2930Sstevel@tonic-gate return (ns_sign2(msg, msglen, msgsize, error, state->key,
2940Sstevel@tonic-gate state->sig, state->siglen,
2950Sstevel@tonic-gate state->sig, &state->siglen, 0,
2960Sstevel@tonic-gate dnptrs, lastdnptr));
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate if (state->siglen > 0) {
2990Sstevel@tonic-gate u_int16_t siglen_n = htons(state->siglen);
3000Sstevel@tonic-gate dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx,
3010Sstevel@tonic-gate NULL, 0, NULL, 0);
3020Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
3030Sstevel@tonic-gate (u_char *)&siglen_n, INT16SZ, NULL, 0);
3040Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
3050Sstevel@tonic-gate state->sig, state->siglen, NULL, 0);
3060Sstevel@tonic-gate state->siglen = 0;
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen,
3100Sstevel@tonic-gate NULL, 0);
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate if (done == 0 && (state->counter % 100 != 0))
3130Sstevel@tonic-gate return (0);
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate cp = msg + *msglen;
3160Sstevel@tonic-gate eob = msg + msgsize;
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /* Name. */
3190Sstevel@tonic-gate n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr);
3200Sstevel@tonic-gate if (n < 0)
3210Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE);
3220Sstevel@tonic-gate cp += n;
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /* Type, class, ttl, length (not filled in yet). */
3250Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ);
3260Sstevel@tonic-gate PUTSHORT(ns_t_tsig, cp);
3270Sstevel@tonic-gate PUTSHORT(ns_c_any, cp);
328*11038SRao.Shoaib@Sun.COM PUTLONG(0, cp); /*%< TTL */
3290Sstevel@tonic-gate lenp = cp;
3300Sstevel@tonic-gate cp += 2;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate /* Alg. */
3330Sstevel@tonic-gate n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL);
3340Sstevel@tonic-gate if (n < 0)
3350Sstevel@tonic-gate return (NS_TSIG_ERROR_NO_SPACE);
3360Sstevel@tonic-gate cp += n;
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate /* Time. */
3390Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
3400Sstevel@tonic-gate PUTSHORT(0, cp);
3410Sstevel@tonic-gate timesigned = time(NULL);
3420Sstevel@tonic-gate PUTLONG(timesigned, cp);
3430Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp);
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate /*
3460Sstevel@tonic-gate * Compute the signature.
3470Sstevel@tonic-gate */
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate /* Digest the time signed and fudge. */
3500Sstevel@tonic-gate cp2 = buf;
351*11038SRao.Shoaib@Sun.COM PUTSHORT(0, cp2); /*%< Top 16 bits of time */
3520Sstevel@tonic-gate PUTLONG(timesigned, cp2);
3530Sstevel@tonic-gate PUTSHORT(NS_TSIG_FUDGE, cp2);
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx,
3560Sstevel@tonic-gate buf, cp2 - buf, NULL, 0);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
3590Sstevel@tonic-gate state->sig, sizeof(state->sig));
3600Sstevel@tonic-gate if (n < 0)
3610Sstevel@tonic-gate return (-ns_r_badkey);
3620Sstevel@tonic-gate state->siglen = n;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate /* Add the signature. */
3650Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + state->siglen);
3660Sstevel@tonic-gate PUTSHORT(state->siglen, cp);
3670Sstevel@tonic-gate memcpy(cp, state->sig, state->siglen);
3680Sstevel@tonic-gate cp += state->siglen;
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate /* The original message ID & error. */
3710Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ + INT16SZ);
372*11038SRao.Shoaib@Sun.COM PUTSHORT(ntohs(hp->id), cp); /*%< already in network order */
3730Sstevel@tonic-gate PUTSHORT(error, cp);
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate /* Other data. */
3760Sstevel@tonic-gate BOUNDS_CHECK(cp, INT16SZ);
3770Sstevel@tonic-gate PUTSHORT(0, cp);
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate /* Go back and fill in the length. */
3800Sstevel@tonic-gate PUTSHORT(cp - lenp - INT16SZ, lenp);
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate hp->arcount = htons(ntohs(hp->arcount) + 1);
3830Sstevel@tonic-gate *msglen = (cp - msg);
3840Sstevel@tonic-gate return (0);
3850Sstevel@tonic-gate }
386*11038SRao.Shoaib@Sun.COM
387*11038SRao.Shoaib@Sun.COM /*! \file */
388