📄 sctp_cookie.c
字号:
memset(k_ipad, 0, sizeof(k_ipad)); memset(k_opad, 0, sizeof(k_opad)); memcpy(k_ipad, key, klen); memcpy(k_opad, key, klen); for ( i=0; i<64; i++ ) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } /* inner */ SHAInit(&context); SHAUpdate(&context, k_ipad, 64); SHAUpdate(&context, text, tlen); SHAFinal(digest, &context); /* outer */ SHAInit(&context); SHAUpdate(&context, k_opad, 64); SHAUpdate(&context, digest, 20); SHAFinal(digest, &context);}/* * ========================================================================= * * MD5 * * ========================================================================= */typedef struct { u32 buf[4]; u32 lo, hi; u32 dat[16];} MD5_CTX;/* The four core functions - F1 is optimized somewhat *//* #define F1(x, y, z) (x & y | ~x & z) */#define F1(x, y, z) (z ^ (x & (y ^ z)))#define F2(x, y, z) F1(z, x, y)#define F3(x, y, z) (x ^ y ^ z)#define F4(x, y, z) (y ^ (x | ~z))/* This is the central step in the MD5 algorithm. */#define MD5STEP(f,w,x,y,z,dat,s) \ (w += f(x,y,z) + dat, w = (w<<s | w>>(32-s)) + x)/* * The core of the MD5 algorithm, this alters an existing MD5 hash to reflect * the addition of 16 longwords of new data. MD5Update blocks the data and * converts bytes into longwords for this routine. */static void MD5Transform(u32 dig[4], u32 const dat[16]){ register u32 a, b, c, d; a = dig[0]; b = dig[1]; c = dig[2]; d = dig[3]; MD5STEP(F1, a, b, c, d, dat[ 0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, dat[ 1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, dat[ 2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, dat[ 3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, dat[ 4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, dat[ 5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, dat[ 6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, dat[ 7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, dat[ 8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, dat[ 9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, dat[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, dat[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, dat[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, dat[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, dat[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, dat[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, dat[ 1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, dat[ 6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, dat[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, dat[ 0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, dat[ 5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, dat[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, dat[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, dat[ 4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, dat[ 9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, dat[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, dat[ 3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, dat[ 8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, dat[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, dat[ 2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, dat[ 7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, dat[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, dat[ 5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, dat[ 8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, dat[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, dat[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, dat[ 1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, dat[ 4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, dat[ 7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, dat[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, dat[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, dat[ 0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, dat[ 3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, dat[ 6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, dat[ 9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, dat[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, dat[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, dat[ 2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, dat[ 0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, dat[ 7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, dat[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, dat[ 5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, dat[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, dat[ 3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, dat[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, dat[ 1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, dat[ 8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, dat[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, dat[ 6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, dat[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, dat[ 4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, dat[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, dat[ 2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, dat[ 9] + 0xeb86d391, 21); dig[0] += a; dig[1] += b; dig[2] += c; dig[3] += d;}#ifdef __BIG_ENDIANvoidbyteSwap(u32 *buf, unsigned cnt){ u8 *p = (u8 *)buf; do { *buf++ = (u32)((unsigned)p[3] << 8 | p[2]) << 16 | ((unsigned)p[1] << 8 | p[0]); p += 4; } while (--cnt);}#else#define byteSwap(__buf,__cnt)#endif/* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */static void MD5Init(MD5_CTX *md5){ md5->buf[0] = 0x67452301; md5->buf[1] = 0xefcdab89; md5->buf[2] = 0x98badcfe; md5->buf[3] = 0x10325476; md5->lo = 0; md5->hi = 0;}/* * Update context to reflect the concatenation of another buffer full * of bytes. */static void MD5Update(MD5_CTX *md5, u8 const *buf, unsigned len){ u32 t; /* Update byte count */ t = md5->lo; if ( (md5->lo = t+len) < t) md5->hi++; /* Carry from low to high */ t = 64 - (t & 0x3f); /* Space available in md5->dat (at least 1) */ if ( t > len ) { memcpy((u8 *)md5->dat+64-t, buf, len); return; } /* First chunk is an odd size */ memcpy((u8 *)md5->dat+64-t, buf, t); byteSwap(md5->dat, 16); MD5Transform(md5->buf, md5->dat); buf += t; len -= t; /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(md5->dat, buf, 64); byteSwap(md5->dat, 16); MD5Transform(md5->buf, md5->dat); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(md5->dat, buf, len);}/* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */static void MD5Final(u8 dig[16], MD5_CTX *md5){ int count = md5->lo & 0x3f; /* Number of bytes in md5->dat */ u8 *p = (u8 *)md5->dat + count; /* Set the first char of padding to 0x80. There is always room. */ *p++ = 0x80; /* Bytes of padding needed to make 56 bytes (-8..55) */ count = 56 - 1 - count; if (count < 0) { /* Padding forces an extra block */ memset(p, 0, count+8); byteSwap(md5->dat, 16); MD5Transform(md5->buf, md5->dat); p = (u8 *)md5->dat; count = 56; } memset(p, 0, count); byteSwap(md5->dat, 14); /* Append length in bits and transform */ md5->dat[14] = md5->lo << 3; md5->dat[15] = md5->hi << 3 | md5->lo >> 29; MD5Transform(md5->buf, md5->dat); byteSwap(md5->buf, 4); memcpy(dig, md5->buf, 16); memset(md5, 0, sizeof(md5)); /* In case it's sensitive */}/* * ------------------------------------------------------------------------- * * HMAC-MD5 * * ------------------------------------------------------------------------- * * Code adapted directly from RFC 2401. */static void hmac_md5(u8 *text, int tlen, u8 *key, int klen, u8 *digest){ MD5_CTX context; u8 k_ipad[65]; u8 k_opad[65]; u8 tk[16]; int i; if ( klen > 64 ) { MD5_CTX ctx; MD5Init(&ctx); MD5Update(&ctx, key, klen); MD5Final(tk, &ctx); key = tk; klen = 16; } memset(k_ipad, 0, sizeof(k_ipad)); memset(k_opad, 0, sizeof(k_opad)); memcpy(k_ipad, key, klen); memcpy(k_opad, key, klen); for ( i=0; i<64; i++ ) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } /* inner */ MD5Init(&context); MD5Update(&context, k_ipad, 64); MD5Update(&context, text, tlen); MD5Final(digest, &context); /* outer */ MD5Init(&context); MD5Update(&context, k_opad, 64); MD5Update(&context, digest, 16); MD5Final(digest, &context);}/* * ========================================================================= * * SCTP Key handling * * ========================================================================= * * This algorithm uses 2^n keys (NUM_KEYS) which are recycled quickly and * evenly. Each key has a key tag which is placed in the SCTP cookie. Each * key is valid for the cookie lifespan plus a key life. The key life should * be set to whatever cookie life increment has been permitted. When a cookie * is checked for validity, its MAC is verified using the key with the key tag * in the cookie. If the key has already been recycled, the tagged key will * not fit the lock anymore. Note that the keys are cycled only as quickly as * the requests for signatures come in. This adds another degree of * variability to the key selection. */struct sctp_key { union { u32 seq[16]; u8 key[64]; } u; unsigned int last; unsigned long created;};#define NUM_KEYS 4static struct sctp_key sctp_keys[NUM_KEYS];static int sctp_current_key = 0;extern u32 secure_tcp_sequence_number(u32, u32, u16, u16);/* * TODO: This rekeying is too predicatable. There are several things bad * about it: (1) the key has a historic component, which is bad; (2) initial * keys have zeros in alot of places which makes it no stronger than if only * 32 bit keys were used. */static void sctp_rekey(k) int k;{ u32 *seq; int n = (sctp_keys[k].last+1)&0xf; sctp_keys[k].last = n; seq = &sctp_keys[k].u.seq[n]; *seq = secure_tcp_sequence_number( *(seq+1), *(seq+2), *(seq+3), *(seq+4));}static int sctp_get_key(sp) sctp_t *sp;{ int k = sctp_current_key; unsigned long duration = ((sp->ck_life+NUM_KEYS-1)/NUM_KEYS) + sp->ck_inc; unsigned long created = sctp_keys[k].created; if ( !created ) { sctp_keys[k].created = jiffies; return k; } if ( created + duration < jiffies ) { k = (k+1)%NUM_KEYS; sctp_rekey(k); sctp_current_key = k; } return k;}static void sctp_hmac(sp, text, tlen, key, klen, hmac) sctp_t *sp; u8 *text; int tlen; u8 *key; int klen; u8 *hmac;{ memset(hmac, 0xff, HMAC_SIZE); switch ( sp->hmac ) { case SCTP_HMAC_SHA_1: hmac_sha1(text, tlen, key, klen, hmac); break; case SCTP_HMAC_MD5: hmac_md5(text, tlen, key, klen, hmac); break; default: case SCTP_HMAC_NONE: break; }}void sctp_sign_cookie(sp, ck) sctp_t *sp; struct sctp_cookie *ck;{ u8 *text = (u8 *)ck; int tlen = raw_cookie_size(ck); int ktag = sctp_get_key(sp); u8 *key = sctp_keys[ktag].u.key; int klen = sizeof(sctp_keys[0].u.key); u8 *hmacp = ((u8 *)ck)+tlen;#if 0 int i; ptrace(("Signing cookie:\n")); printk("text = %u, tlen = %d\n",(uint)text, tlen); printk("ktag = %d, klen = %d\n",ktag,klen); printk("key = "); for ( i=0; i<klen; i++ ) printk("%02x",key[i]); printk("\n");#endif ck->key_tag = ktag; sctp_hmac(sp, text, tlen, key, klen, hmacp);#if 0 printk("hmac = "); for ( i=0; i<HMAC_SIZE; i++ ) printk("%02x",hmacp[i]); printk("\n");#endif}/* Note: caller must verify length of cookie */int sctp_verify_cookie(sp, ck) sctp_t *sp; struct sctp_cookie *ck;{ u8 hmac[HMAC_SIZE]; u8 *text = (u8 *)ck; int tlen = raw_cookie_size(ck); int ktag = (ck->key_tag)%NUM_KEYS; u8 *key = sctp_keys[ktag].u.key; int klen = sizeof(sctp_keys[0].u.key); u8 *hmacp = ((u8 *)ck)+tlen;#if 0 int i; ptrace(("Verifying cookie:\n")); printk("text = %u, tlen = %d\n",(uint)text, tlen); printk("ktag = %d, klen = %d\n",ktag,klen); printk("key = "); for ( i=0; i<klen; i++ ) printk("%02x",key[i]); printk("\n"); printk("hmac = "); for ( i=0; i<HMAC_SIZE; i++ ) printk("%02x",hmacp[i]); printk("\n");#endif sctp_hmac(sp, text, tlen, key, klen, hmac);#if 0 printk("hmac = "); for ( i=0; i<HMAC_SIZE; i++ ) printk("%02x",hmac[i]); printk("\n");#endif return memcmp(hmacp, hmac, HMAC_SIZE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -