DF-3567 / bfkat.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | /* * bfkat.c - known-answer test for sys/crypto/blowfish/bf_skey.c + bf_enc.c * (compiled as userland objects from the guest's /usr/src/sys tree). * * Vectors: Bruce Schneier, "Blowfish" test vectors (v1.0, 8-byte keys), * published with the reference implementation. * Wrap-loop/clamp tests cross-checked against openssl if available. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <crypto/blowfish/blowfish.h> struct vec { const char *k, *p, *c; }; /* Schneier's published set (hex) */ static struct vec vecs[] = { {"0000000000000000","0000000000000000","4EF997456198DD78"}, {"FFFFFFFFFFFFFFFF","FFFFFFFFFFFFFFFF","51866FD5B85ECB8A"}, {"3000000000000000","1000000000000001","7D856F9A613063F2"}, {"1111111111111111","1111111111111111","2466DD878B963C9D"}, {"0123456789ABCDEF","1111111111111111","61F9C3802281B096"}, {"1111111111111111","0123456789ABCDEF","7D0CC630AFDA1EC7"}, {"FEDCBA9876543210","0123456789ABCDEF","0ACEAB0FC6A0A28D"}, {"7CA110454A1A6E57","01A1D6D039776742","59C68245EB05282B"}, {"0131D9619DC1376E","5CD54CA83DEF57DA","B1B8CC0B250F09A0"}, }; static int hex2bin(const char *hex, unsigned char *out, int maxlen) { int n = 0; while (hex[0] && hex[1] && n < maxlen) { unsigned v; sscanf(hex, "%2x", &v); out[n++] = (unsigned char)v; hex += 2; } return n; } static void bin2hex(const unsigned char *b, int n, char *out) { int i; for (i = 0; i < n; i++) sprintf(out + 2*i, "%02X", b[i]); out[2*n] = 0; } int main(void) { BF_KEY key; int i, fails = 0; for (i = 0; i < (int)(sizeof(vecs)/sizeof(vecs[0])); i++) { unsigned char kb[8], pb[8], got[16], exp[8]; char gothex[64]; BF_LONG d[2]; hex2bin(vecs[i].k, kb, 8); hex2bin(vecs[i].p, pb, 8); hex2bin(vecs[i].c, exp, 8); BF_set_key(&key, 8, kb); d[0] = ((BF_LONG)pb[0] << 24) | ((BF_LONG)pb[1] << 16) | ((BF_LONG)pb[2] << 8) | (BF_LONG)pb[3]; d[1] = ((BF_LONG)pb[4] << 24) | ((BF_LONG)pb[5] << 16) | ((BF_LONG)pb[6] << 8) | (BF_LONG)pb[7]; BF_encrypt(d, &key); got[0] = d[0] >> 24; got[1] = d[0] >> 16; got[2] = d[0] >> 8; got[3] = d[0]; got[4] = d[1] >> 24; got[5] = d[1] >> 16; got[6] = d[1] >> 8; got[7] = d[1]; bin2hex(got, 8, gothex); if (strcmp(gothex, vecs[i].c) != 0) { printf("FAIL vec %d: got %s want %s\n", i, gothex, vecs[i].c); fails++; } else { printf("PASS vec %d: %s\n", i, gothex); } } /* * Wrap-loop demo: variable-length keys 1..72 and a >72 key (clamp). * No public KAT for these; emit ciphertext for openssl cross-match. */ { unsigned char keybuf[100], pt[8] = "BLOWFISH", got[8]; char gothex[64]; int lens[] = {1, 2, 3, 4, 5, 7, 8, 12, 16, 20, 24, 32, 56, 71, 72, 73, 100}; size_t l; memset(keybuf, 0, sizeof(keybuf)); for (l = 0; l < sizeof(keybuf); l++) keybuf[l] = (unsigned char)(l + 1); /* distinguishable */ for (i = 0; i < (int)(sizeof(lens)/sizeof(lens[0])); i++) { BF_LONG d[2]; l = lens[i]; BF_set_key(&key, l, keybuf); memcpy(got, pt, 8); d[0] = ((BF_LONG)got[0] << 24) | ((BF_LONG)got[1] << 16) | ((BF_LONG)got[2] << 8) | (BF_LONG)got[3]; d[1] = ((BF_LONG)got[4] << 24) | ((BF_LONG)got[5] << 16) | ((BF_LONG)got[6] << 8) | (BF_LONG)got[7]; BF_encrypt(d, &key); got[0] = d[0] >> 24; got[1] = d[0] >> 16; got[2] = d[0] >> 8; got[3] = d[0]; got[4] = d[1] >> 24; got[5] = d[1] >> 16; got[6] = d[1] >> 8; got[7] = d[1]; bin2hex(got, 8, gothex); printf("WRAP len=%d ct=%s\n", (int)l, gothex); } /* clamp equivalence: len=73..100 must equal len=72 result? NO - * clamp keeps first 72 bytes; len=100 == len=72 output. Check. */ { BF_LONG d[2]; unsigned char g72[8], g100[8]; BF_set_key(&key, 72, keybuf); d[0] = ((BF_LONG)pt[0] << 24) | ((BF_LONG)pt[1] << 16) | ((BF_LONG)pt[2] << 8) | (BF_LONG)pt[3]; d[1] = ((BF_LONG)pt[4] << 24) | ((BF_LONG)pt[5] << 16) | ((BF_LONG)pt[6] << 8) | (BF_LONG)pt[7]; BF_encrypt(d, &key); g72[0]=d[0]>>24;g72[1]=d[0]>>16;g72[2]=d[0]>>8;g72[3]=d[0]; g72[4]=d[1]>>24;g72[5]=d[1]>>16;g72[6]=d[1]>>8;g72[7]=d[1]; BF_set_key(&key, 100, keybuf); d[0] = ((BF_LONG)pt[0] << 24) | ((BF_LONG)pt[1] << 16) | ((BF_LONG)pt[2] << 8) | (BF_LONG)pt[3]; d[1] = ((BF_LONG)pt[4] << 24) | ((BF_LONG)pt[5] << 16) | ((BF_LONG)pt[6] << 8) | (BF_LONG)pt[7]; BF_encrypt(d, &key); g100[0]=d[0]>>24;g100[1]=d[0]>>16;g100[2]=d[0]>>8;g100[3]=d[0]; g100[4]=d[1]>>24;g100[5]=d[1]>>16;g100[6]=d[1]>>8;g100[7]=d[1]; if (memcmp(g72, g100, 8) == 0) printf("PASS clamp: len=100 == len=72\n"); else { printf("FAIL clamp: len=100 != len=72\n"); fails++; } } } printf("%s: %d failures\n", fails ? "RESULT-FAIL" : "RESULT-PASS", fails); return fails ? 1 : 0; } |