DF-4577 / df4577_sim.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 | /* * DF-4577 proof-of-arithmetic: simulate intel_hdcp_validate_v_prime's * KSV->HDCP_SHA_TEXT byte-stream construction (DF/sys form) versus the * upstream-fixed form (master: off = (4 - j - 1 - sha_leftovers)*8) and * the true required stream, for N downstream devices (5-byte KSVs). * * Pure userspace simulation on the audit host. Compile: cc -o sim sim.c */ #include <stdio.h> #include <string.h> #define KSV_LEN 5 #define MAXN 6 /* emit-word callback: gets each 32-bit word the driver would write */ static int words_old[16][8], words_new[16][8]; static int nw_old[MAXN + 1], nw_new[MAXN + 1]; static void sim(int n, int fixed) { int sha_leftovers = 0, sha_text = 0, i, j; int (*w)[8] = fixed ? words_new : words_old; int *nw = fixed ? &nw_new[n] : &nw_old[n]; int idx = 0; memset(w, 0, sizeof(words_old)); *nw = 0; for (i = 0; i < n; i++) { int ksv[KSV_LEN]; int sha_empty; for (j = 0; j < KSV_LEN; j++) ksv[j] = i * KSV_LEN + j + 1; /* stream bytes 1,2,3... */ sha_empty = 4 - sha_leftovers; for (j = 0; j < sha_empty; j++) { int off = fixed ? (4 - j - 1 - sha_leftovers) * 8 : (4 - j - 1) * 8; sha_text |= ksv[j] << off; } w[n][idx++] = sha_text; /* intel_write_sha_text(sha_text) */ sha_leftovers = KSV_LEN - sha_empty; sha_text = 0; for (j = 0; j < sha_leftovers; j++) sha_text |= ksv[sha_empty + j] << ((4 - j - 1) * 8); if (4 > sha_leftovers) continue; w[n][idx++] = sha_text; sha_leftovers = 0; sha_text = 0; } *nw = idx; } static void dump_words(const char *tag, int (*w)[8], int n, int nw) { int i, b; printf(" %-10s:", tag); for (i = 0; i < nw; i++) for (b = 3; b >= 0; b--) printf(" %2d", (w[n][i] >> (b * 8)) & 0xff); printf("\n"); } int main(void) { int n; for (n = 1; n <= 5; n++) { int bytes = n * KSV_LEN, k, true_stream[64]; sim(n, 0); /* DF / pre-fix form */ sim(n, 1); /* upstream-fixed form */ printf("N=%d downstream device(s), %d KSV bytes:\n", n, bytes); for (k = 0; k < bytes; k++) true_stream[k] = k + 1; printf(" required :"); for (k = 0; k < bytes; k++) printf(" %2d", true_stream[k]); printf("\n"); dump_words("DF (old)", words_old, n, nw_old[n]); dump_words("upstream", words_new, n, nw_new[n]); /* compare DF stream vs required over the KSV bytes */ int df[64], ndf = 0, ok = 1; for (k = 0; k < nw_old[n]; k++) { int b; for (b = 3; b >= 0; b--) df[ndf++] = (words_old[n][k] >> (b * 8)) & 0xff; } for (k = 0; k < bytes; k++) if (df[k] != true_stream[k]) ok = 0; printf(" => DF KSV stream %s the required concatenation", ok ? "MATCHES" : "CORRUPTS"); if (!ok) { printf(" (first divergence at byte "); for (k = 0; k < bytes; k++) if (df[k] != true_stream[k]) { printf("%d: got %d want %d", k + 1, df[k], true_stream[k]); break; } printf(")"); } printf("\n\n"); } return 0; } |