1*bf198cc6Smillert /* $OpenBSD: crc.c,v 1.5 2019/01/25 00:19:25 millert Exp $ */
2cc6ea15bSmillert
3cc6ea15bSmillert /*
4*bf198cc6Smillert * Copyright (c) 2004 Todd C. Miller <millert@openbsd.org>
5cc6ea15bSmillert *
6cc6ea15bSmillert * Permission to use, copy, modify, and distribute this software for any
7cc6ea15bSmillert * purpose with or without fee is hereby granted, provided that the above
8cc6ea15bSmillert * copyright notice and this permission notice appear in all copies.
9cc6ea15bSmillert *
10cc6ea15bSmillert * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11cc6ea15bSmillert * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12cc6ea15bSmillert * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13cc6ea15bSmillert * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14cc6ea15bSmillert * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15cc6ea15bSmillert * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16cc6ea15bSmillert * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17cc6ea15bSmillert */
18cc6ea15bSmillert
19cc6ea15bSmillert #include <sys/types.h>
20cc6ea15bSmillert
21cc6ea15bSmillert #include <errno.h>
22cc6ea15bSmillert #include <fcntl.h>
23cc6ea15bSmillert #include <stdio.h>
24cc6ea15bSmillert #include <string.h>
25cc6ea15bSmillert #include <unistd.h>
26cc6ea15bSmillert
27cc6ea15bSmillert #include "crc.h"
28cc6ea15bSmillert
29cc6ea15bSmillert /*
30cc6ea15bSmillert * Table-driven version of the following polynomial from POSIX 1003.2:
31cc6ea15bSmillert * G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 +
32cc6ea15bSmillert * x^7 + x^5 + x^4 + x^2 + x + 1
33cc6ea15bSmillert */
34cc6ea15bSmillert static const u_int32_t crc32tab[] = {
35cc6ea15bSmillert 0x00000000U,
36cc6ea15bSmillert 0x04c11db7U, 0x09823b6eU, 0x0d4326d9U, 0x130476dcU, 0x17c56b6bU,
37cc6ea15bSmillert 0x1a864db2U, 0x1e475005U, 0x2608edb8U, 0x22c9f00fU, 0x2f8ad6d6U,
38cc6ea15bSmillert 0x2b4bcb61U, 0x350c9b64U, 0x31cd86d3U, 0x3c8ea00aU, 0x384fbdbdU,
39cc6ea15bSmillert 0x4c11db70U, 0x48d0c6c7U, 0x4593e01eU, 0x4152fda9U, 0x5f15adacU,
40cc6ea15bSmillert 0x5bd4b01bU, 0x569796c2U, 0x52568b75U, 0x6a1936c8U, 0x6ed82b7fU,
41cc6ea15bSmillert 0x639b0da6U, 0x675a1011U, 0x791d4014U, 0x7ddc5da3U, 0x709f7b7aU,
42cc6ea15bSmillert 0x745e66cdU, 0x9823b6e0U, 0x9ce2ab57U, 0x91a18d8eU, 0x95609039U,
43cc6ea15bSmillert 0x8b27c03cU, 0x8fe6dd8bU, 0x82a5fb52U, 0x8664e6e5U, 0xbe2b5b58U,
44cc6ea15bSmillert 0xbaea46efU, 0xb7a96036U, 0xb3687d81U, 0xad2f2d84U, 0xa9ee3033U,
45cc6ea15bSmillert 0xa4ad16eaU, 0xa06c0b5dU, 0xd4326d90U, 0xd0f37027U, 0xddb056feU,
46cc6ea15bSmillert 0xd9714b49U, 0xc7361b4cU, 0xc3f706fbU, 0xceb42022U, 0xca753d95U,
47cc6ea15bSmillert 0xf23a8028U, 0xf6fb9d9fU, 0xfbb8bb46U, 0xff79a6f1U, 0xe13ef6f4U,
48cc6ea15bSmillert 0xe5ffeb43U, 0xe8bccd9aU, 0xec7dd02dU, 0x34867077U, 0x30476dc0U,
49cc6ea15bSmillert 0x3d044b19U, 0x39c556aeU, 0x278206abU, 0x23431b1cU, 0x2e003dc5U,
50cc6ea15bSmillert 0x2ac12072U, 0x128e9dcfU, 0x164f8078U, 0x1b0ca6a1U, 0x1fcdbb16U,
51cc6ea15bSmillert 0x018aeb13U, 0x054bf6a4U, 0x0808d07dU, 0x0cc9cdcaU, 0x7897ab07U,
52cc6ea15bSmillert 0x7c56b6b0U, 0x71159069U, 0x75d48ddeU, 0x6b93dddbU, 0x6f52c06cU,
53cc6ea15bSmillert 0x6211e6b5U, 0x66d0fb02U, 0x5e9f46bfU, 0x5a5e5b08U, 0x571d7dd1U,
54cc6ea15bSmillert 0x53dc6066U, 0x4d9b3063U, 0x495a2dd4U, 0x44190b0dU, 0x40d816baU,
55cc6ea15bSmillert 0xaca5c697U, 0xa864db20U, 0xa527fdf9U, 0xa1e6e04eU, 0xbfa1b04bU,
56cc6ea15bSmillert 0xbb60adfcU, 0xb6238b25U, 0xb2e29692U, 0x8aad2b2fU, 0x8e6c3698U,
57cc6ea15bSmillert 0x832f1041U, 0x87ee0df6U, 0x99a95df3U, 0x9d684044U, 0x902b669dU,
58cc6ea15bSmillert 0x94ea7b2aU, 0xe0b41de7U, 0xe4750050U, 0xe9362689U, 0xedf73b3eU,
59cc6ea15bSmillert 0xf3b06b3bU, 0xf771768cU, 0xfa325055U, 0xfef34de2U, 0xc6bcf05fU,
60cc6ea15bSmillert 0xc27dede8U, 0xcf3ecb31U, 0xcbffd686U, 0xd5b88683U, 0xd1799b34U,
61cc6ea15bSmillert 0xdc3abdedU, 0xd8fba05aU, 0x690ce0eeU, 0x6dcdfd59U, 0x608edb80U,
62cc6ea15bSmillert 0x644fc637U, 0x7a089632U, 0x7ec98b85U, 0x738aad5cU, 0x774bb0ebU,
63cc6ea15bSmillert 0x4f040d56U, 0x4bc510e1U, 0x46863638U, 0x42472b8fU, 0x5c007b8aU,
64cc6ea15bSmillert 0x58c1663dU, 0x558240e4U, 0x51435d53U, 0x251d3b9eU, 0x21dc2629U,
65cc6ea15bSmillert 0x2c9f00f0U, 0x285e1d47U, 0x36194d42U, 0x32d850f5U, 0x3f9b762cU,
66cc6ea15bSmillert 0x3b5a6b9bU, 0x0315d626U, 0x07d4cb91U, 0x0a97ed48U, 0x0e56f0ffU,
67cc6ea15bSmillert 0x1011a0faU, 0x14d0bd4dU, 0x19939b94U, 0x1d528623U, 0xf12f560eU,
68cc6ea15bSmillert 0xf5ee4bb9U, 0xf8ad6d60U, 0xfc6c70d7U, 0xe22b20d2U, 0xe6ea3d65U,
69cc6ea15bSmillert 0xeba91bbcU, 0xef68060bU, 0xd727bbb6U, 0xd3e6a601U, 0xdea580d8U,
70cc6ea15bSmillert 0xda649d6fU, 0xc423cd6aU, 0xc0e2d0ddU, 0xcda1f604U, 0xc960ebb3U,
71cc6ea15bSmillert 0xbd3e8d7eU, 0xb9ff90c9U, 0xb4bcb610U, 0xb07daba7U, 0xae3afba2U,
72cc6ea15bSmillert 0xaafbe615U, 0xa7b8c0ccU, 0xa379dd7bU, 0x9b3660c6U, 0x9ff77d71U,
73cc6ea15bSmillert 0x92b45ba8U, 0x9675461fU, 0x8832161aU, 0x8cf30badU, 0x81b02d74U,
74cc6ea15bSmillert 0x857130c3U, 0x5d8a9099U, 0x594b8d2eU, 0x5408abf7U, 0x50c9b640U,
75cc6ea15bSmillert 0x4e8ee645U, 0x4a4ffbf2U, 0x470cdd2bU, 0x43cdc09cU, 0x7b827d21U,
76cc6ea15bSmillert 0x7f436096U, 0x7200464fU, 0x76c15bf8U, 0x68860bfdU, 0x6c47164aU,
77cc6ea15bSmillert 0x61043093U, 0x65c52d24U, 0x119b4be9U, 0x155a565eU, 0x18197087U,
78cc6ea15bSmillert 0x1cd86d30U, 0x029f3d35U, 0x065e2082U, 0x0b1d065bU, 0x0fdc1becU,
79cc6ea15bSmillert 0x3793a651U, 0x3352bbe6U, 0x3e119d3fU, 0x3ad08088U, 0x2497d08dU,
80cc6ea15bSmillert 0x2056cd3aU, 0x2d15ebe3U, 0x29d4f654U, 0xc5a92679U, 0xc1683bceU,
81cc6ea15bSmillert 0xcc2b1d17U, 0xc8ea00a0U, 0xd6ad50a5U, 0xd26c4d12U, 0xdf2f6bcbU,
82cc6ea15bSmillert 0xdbee767cU, 0xe3a1cbc1U, 0xe760d676U, 0xea23f0afU, 0xeee2ed18U,
83cc6ea15bSmillert 0xf0a5bd1dU, 0xf464a0aaU, 0xf9278673U, 0xfde69bc4U, 0x89b8fd09U,
84cc6ea15bSmillert 0x8d79e0beU, 0x803ac667U, 0x84fbdbd0U, 0x9abc8bd5U, 0x9e7d9662U,
85cc6ea15bSmillert 0x933eb0bbU, 0x97ffad0cU, 0xafb010b1U, 0xab710d06U, 0xa6322bdfU,
86cc6ea15bSmillert 0xa2f33668U, 0xbcb4666dU, 0xb8757bdaU, 0xb5365d03U, 0xb1f740b4U
87cc6ea15bSmillert };
88cc6ea15bSmillert
89cc6ea15bSmillert void
CKSUM_Init(CKSUM_CTX * ctx)90cc6ea15bSmillert CKSUM_Init(CKSUM_CTX *ctx)
91cc6ea15bSmillert {
92cc6ea15bSmillert ctx->crc = 0;
93cc6ea15bSmillert ctx->len = 0;
94cc6ea15bSmillert }
95cc6ea15bSmillert
96cc6ea15bSmillert #define UPDATE(crc, byte) do \
97cc6ea15bSmillert (crc) = ((crc) << 8) ^ crc32tab[((crc) >> 24) ^ (byte)]; \
98cc6ea15bSmillert while(0)
99cc6ea15bSmillert
100cc6ea15bSmillert void
CKSUM_Update(CKSUM_CTX * ctx,const unsigned char * buf,size_t len)101cc6ea15bSmillert CKSUM_Update(CKSUM_CTX *ctx, const unsigned char *buf, size_t len)
102cc6ea15bSmillert {
103cc6ea15bSmillert size_t i;
104cc6ea15bSmillert
105cc6ea15bSmillert for (i = 0; i < len; i++)
106cc6ea15bSmillert UPDATE(ctx->crc, buf[i]);
107cc6ea15bSmillert ctx->len += len;
108cc6ea15bSmillert }
109cc6ea15bSmillert
110cc6ea15bSmillert void
CKSUM_Final(CKSUM_CTX * ctx)111cc6ea15bSmillert CKSUM_Final(CKSUM_CTX *ctx)
112cc6ea15bSmillert {
113cc6ea15bSmillert off_t len = ctx->len;
114cc6ea15bSmillert
115cc6ea15bSmillert /* add in number of bytes read and finish */
116cc6ea15bSmillert while (len != 0) {
117cc6ea15bSmillert UPDATE(ctx->crc, len & 0xff);
118cc6ea15bSmillert len >>= 8;
119cc6ea15bSmillert }
120cc6ea15bSmillert ctx->crc = ~ctx->crc;
121cc6ea15bSmillert }
122cc6ea15bSmillert
123cc6ea15bSmillert char *
CKSUM_End(CKSUM_CTX * ctx,char * outstr)124cc6ea15bSmillert CKSUM_End(CKSUM_CTX *ctx, char *outstr)
125cc6ea15bSmillert {
126cc6ea15bSmillert CKSUM_Final(ctx);
127cc6ea15bSmillert
128cc6ea15bSmillert if (outstr == NULL) {
129cc6ea15bSmillert if (asprintf(&outstr, "%u %lld", ctx->crc, ctx->len) == -1)
130cc6ea15bSmillert return (NULL);
131cc6ea15bSmillert } else {
132617ad1c9Sderaadt (void)snprintf(outstr, (size_t)CKSUM_DIGEST_STRING_LENGTH,
133617ad1c9Sderaadt "%u %lld", ctx->crc, ctx->len);
134cc6ea15bSmillert }
135cc6ea15bSmillert
136cc6ea15bSmillert return (outstr);
137cc6ea15bSmillert }
138