The Go Programming Language

Text file src/cmd/gc/md5.c

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// 64-bit MD5 (does full MD5 but returns 64 bits only).
     6	// Translation of ../../pkg/crypto/md5/md5*.go.
     7	
     8	#include "go.h"
     9	#include "md5.h"
    10	
    11	static int md5block(MD5 *dig, uchar *p, int nn);
    12	
    13	enum {
    14		_Chunk = 64
    15	};
    16	
    17	#define _Init0 0x67452301
    18	#define _Init1 0xEFCDAB89
    19	#define _Init2 0x98BADCFE
    20	#define _Init3 0x10325476
    21	
    22	void
    23	md5reset(MD5 *d)
    24	{
    25		d->s[0] = _Init0;
    26		d->s[1] = _Init1;
    27		d->s[2] = _Init2;
    28		d->s[3] = _Init3;
    29		d->nx = 0;
    30		d->len = 0;
    31	}
    32	
    33	void
    34	md5write(MD5 *d, uchar *p, int nn)
    35	{
    36		int i, n;
    37	
    38		d->len += nn;
    39		if(d->nx > 0) {
    40			n = nn;
    41			if(n > _Chunk - d->nx)
    42				n = _Chunk - d->nx;
    43			for(i=0; i<n; i++)
    44				d->x[d->nx+i] = p[i];
    45			d->nx += n;
    46			if(d->nx == _Chunk) {
    47				md5block(d, d->x, _Chunk);
    48				d->nx = 0;
    49			}
    50			p += n;
    51			nn -= n;
    52		}
    53		n = md5block(d, p, nn);
    54		p += n;
    55		nn -= n;
    56		if(nn > 0) {
    57			for(i=0; i<nn; i++)
    58				d->x[i] = p[i];
    59			d->nx = nn;
    60		}
    61	}
    62	
    63	uint64
    64	md5sum(MD5 *d)
    65	{
    66		uchar tmp[64];
    67		int i;
    68		uint64 len;
    69	
    70		// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
    71		len = d->len;
    72		memset(tmp, 0, sizeof tmp);
    73		tmp[0] = 0x80;
    74		if(len%64 < 56)
    75			md5write(d, tmp, 56-len%64);
    76		else
    77			md5write(d, tmp, 64+56-len%64);
    78	
    79		// Length in bits.
    80		len <<= 3;
    81		for(i=0; i<8; i++)
    82			tmp[i] = len>>(8*i);
    83		md5write(d, tmp, 8);
    84	
    85		if(d->nx != 0)
    86			fatal("md5sum");
    87	
    88		return d->s[0] | ((uint64)d->s[1]<<32);
    89	}
    90	
    91	
    92	// MD5 block step.
    93	// In its own file so that a faster assembly or C version
    94	// can be substituted easily.
    95	
    96	// table[i] = int((1<<32) * abs(sin(i+1 radians))).
    97	static uint32 table[64] = {
    98		// round 1
    99		0xd76aa478,
   100		0xe8c7b756,
   101		0x242070db,
   102		0xc1bdceee,
   103		0xf57c0faf,
   104		0x4787c62a,
   105		0xa8304613,
   106		0xfd469501,
   107		0x698098d8,
   108		0x8b44f7af,
   109		0xffff5bb1,
   110		0x895cd7be,
   111		0x6b901122,
   112		0xfd987193,
   113		0xa679438e,
   114		0x49b40821,
   115	
   116		// round 2
   117		0xf61e2562,
   118		0xc040b340,
   119		0x265e5a51,
   120		0xe9b6c7aa,
   121		0xd62f105d,
   122		0x2441453,
   123		0xd8a1e681,
   124		0xe7d3fbc8,
   125		0x21e1cde6,
   126		0xc33707d6,
   127		0xf4d50d87,
   128		0x455a14ed,
   129		0xa9e3e905,
   130		0xfcefa3f8,
   131		0x676f02d9,
   132		0x8d2a4c8a,
   133	
   134		// round3
   135		0xfffa3942,
   136		0x8771f681,
   137		0x6d9d6122,
   138		0xfde5380c,
   139		0xa4beea44,
   140		0x4bdecfa9,
   141		0xf6bb4b60,
   142		0xbebfbc70,
   143		0x289b7ec6,
   144		0xeaa127fa,
   145		0xd4ef3085,
   146		0x4881d05,
   147		0xd9d4d039,
   148		0xe6db99e5,
   149		0x1fa27cf8,
   150		0xc4ac5665,
   151	
   152		// round 4
   153		0xf4292244,
   154		0x432aff97,
   155		0xab9423a7,
   156		0xfc93a039,
   157		0x655b59c3,
   158		0x8f0ccc92,
   159		0xffeff47d,
   160		0x85845dd1,
   161		0x6fa87e4f,
   162		0xfe2ce6e0,
   163		0xa3014314,
   164		0x4e0811a1,
   165		0xf7537e82,
   166		0xbd3af235,
   167		0x2ad7d2bb,
   168		0xeb86d391,
   169	};
   170	
   171	static uint32 shift1[] = { 7, 12, 17, 22 };
   172	static uint32 shift2[] = { 5, 9, 14, 20 };
   173	static uint32 shift3[] = { 4, 11, 16, 23 };
   174	static uint32 shift4[] = { 6, 10, 15, 21 };
   175	
   176	static int
   177	md5block(MD5 *dig, uchar *p, int nn)
   178	{
   179		uint32 a, b, c, d, aa, bb, cc, dd;
   180		int i, j, n;
   181		uint32 X[16];
   182	
   183		a = dig->s[0];
   184		b = dig->s[1];
   185		c = dig->s[2];
   186		d = dig->s[3];
   187		n = 0;
   188	
   189		while(nn >= _Chunk) {
   190			aa = a;
   191			bb = b;
   192			cc = c;
   193			dd = d;
   194	
   195			for(i=0; i<16; i++) {
   196				j = i*4;
   197				X[i] = p[j] | (p[j+1]<<8) | (p[j+2]<<16) | (p[j+3]<<24);
   198			}
   199	
   200			// Round 1.
   201			for(i=0; i<16; i++) {
   202				uint32 x, t, s, f;
   203				x = i;
   204				t = i;
   205				s = shift1[i%4];
   206				f = ((c ^ d) & b) ^ d;
   207				a += f + X[x] + table[t];
   208				a = a<<s | a>>(32-s);
   209				a += b;
   210	
   211				t = d;
   212				d = c;
   213				c = b;
   214				b = a;
   215				a = t;
   216			}
   217	
   218			// Round 2.
   219			for(i=0; i<16; i++) {
   220				uint32 x, t, s, g;
   221	
   222				x = (1+5*i)%16;
   223				t = 16+i;
   224				s = shift2[i%4];
   225				g = ((b ^ c) & d) ^ c;
   226				a += g + X[x] + table[t];
   227				a = a<<s | a>>(32-s);
   228				a += b;
   229	
   230				t = d;
   231				d = c;
   232				c = b;
   233				b = a;
   234				a = t;
   235			}
   236	
   237			// Round 3.
   238			for(i=0; i<16; i++) {
   239				uint32 x, t, s, h;
   240	
   241				x = (5+3*i)%16;
   242				t = 32+i;
   243				s = shift3[i%4];
   244				h = b ^ c ^ d;
   245				a += h + X[x] + table[t];
   246				a = a<<s | a>>(32-s);
   247				a += b;
   248	
   249				t = d;
   250				d = c;
   251				c = b;
   252				b = a;
   253				a = t;
   254			}
   255	
   256			// Round 4.
   257			for(i=0; i<16; i++) {
   258				uint32 x, s, t, ii;
   259	
   260				x = (7*i)%16;
   261				s = shift4[i%4];
   262				t = 48+i;
   263				ii = c ^ (b | ~d);
   264				a += ii + X[x] + table[t];
   265				a = a<<s | a>>(32-s);
   266				a += b;
   267	
   268				t = d;
   269				d = c;
   270				c = b;
   271				b = a;
   272				a = t;
   273			}
   274	
   275			a += aa;
   276			b += bb;
   277			c += cc;
   278			d += dd;
   279	
   280			p += _Chunk;
   281			n += _Chunk;
   282			nn -= _Chunk;
   283		}
   284	
   285		dig->s[0] = a;
   286		dig->s[1] = b;
   287		dig->s[2] = c;
   288		dig->s[3] = d;
   289		return n;
   290	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.