1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have 21 * questions. 22 */ 23 24 package benchmark.crypto; 25 26 import org.openjdk.jmh.annotations.*; 27 import jdk.incubator.vector.*; 28 import java.util.Arrays; 29 30 @State(Scope.Thread) 31 @BenchmarkMode(Mode.Throughput) 32 @Fork(value = 1, jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"}) 33 @Warmup(iterations = 3, time = 3) 34 @Measurement(iterations = 8, time = 2) 35 public class Poly1305Bench { 36 37 @Param({"16384", "65536"}) 38 private int dataSize; 39 40 private Poly1305Vector poly1305_S128 = makePoly1305(Vector.Shape.S_128_BIT); 41 private Poly1305Vector poly1305_S256 = makePoly1305(Vector.Shape.S_256_BIT); 42 private Poly1305Vector poly1305_S512 = makePoly1305(Vector.Shape.S_512_BIT); 43 44 private byte[] in; 45 private byte[] out = new byte[16]; 46 private byte[] key = new byte[32]; 47 48 private static Poly1305Vector makePoly1305(Vector.Shape shape) { 49 Poly1305Vector poly = new Poly1305Vector(shape); 50 runKAT(poly); 51 return poly; 52 } 53 54 @Setup 55 public void setup() { 56 in = new byte[dataSize]; 57 } 58 59 @Benchmark 60 public void auth128() { 61 poly1305_S128.computeTag(key, in, out); 62 } 63 64 @Benchmark 65 public void auth256() { 66 poly1305_S256.computeTag(key, in, out); 67 } 68 69 @Benchmark 70 public void auth512() { 71 poly1305_S512.computeTag(key, in, out); 72 } 73 74 private static class Poly1305Vector { 75 76 private static final int BITS_PER_LIMB = 26; 77 private static final int LIMB_MASK = (1 << BITS_PER_LIMB) - 1; 78 private static final int KEY_LENGTH = 32; 79 private static final int RS_LENGTH = KEY_LENGTH / 2; 80 81 private final Vector.Species<Long> longSpecies; 82 private final Vector.Species<Integer> intSpecies; 83 private final int vectorWidth; 84 private final int parBlockCount; 85 86 private final LongVector.Shuffle<Long> inShuffle0; 87 private final LongVector.Shuffle<Long> inShuffle1; 88 private final IntVector.Mask<Long> inMask; 89 90 public Poly1305Vector(Vector.Shape shape) { 91 92 this.longSpecies = Vector.Species.of(long.class, shape); 93 int intSize = shape.bitSize() / 2; 94 Vector.Shape intShape = Vector.Shape.forBitSize(intSize); 95 this.intSpecies = Vector.Species.of(int.class, intShape); 96 this.vectorWidth = longSpecies.length(); 97 this.parBlockCount = vectorWidth * 16; 98 99 this.inShuffle0 = makeInShuffle0(); 100 this.inShuffle1 = makeInShuffle1(); 101 this.inMask = makeInMask(); 102 } 103 104 private LongVector.Shuffle<Long> makeInShuffle0() { 105 int[] indexArr = new int[vectorWidth]; 106 for (int i = 0; i < indexArr.length; i++) { 107 indexArr[i] = (2 * i) % vectorWidth; 108 } 109 return LongVector.shuffleFromArray(longSpecies, indexArr, 0); 110 } 111 private LongVector.Shuffle<Long> makeInShuffle1() { 112 int[] indexArr = new int[vectorWidth]; 113 for (int i = 0; i < indexArr.length; i++) { 114 indexArr[i] = ((2 * i) % vectorWidth) + 1; 115 } 116 return LongVector.shuffleFromArray(longSpecies, indexArr, 0); 117 } 118 private LongVector.Mask<Long> makeInMask() { 119 boolean[] maskArr = new boolean[vectorWidth]; 120 for (int i = vectorWidth / 2; i < vectorWidth; i++) { 121 maskArr[i] = true; 122 } 123 return LongVector.maskFromArray(longSpecies, maskArr, 0); 124 } 125 126 private static int[] fromByteArray(byte[] buf) { 127 int[] result = new int[5]; 128 129 result[0] 130 = (buf[0] & 0xFF) 131 + ((buf[1] & 0xFF) << 8) 132 + ((buf[2] & 0xFF) << 16) 133 + ((buf[3] & 0x03) << 24); 134 result[1] 135 = ((buf[3] & 0xFF) >> 2) 136 + ((buf[4] & 0xFF) << 6) 137 + ((buf[5] & 0xFF) << 14) 138 + ((buf[6] & 0x0F) << 22); 139 result[2] 140 = ((buf[6] & 0xFF) >> 4) 141 + ((buf[7] & 0xFF) << 4) 142 + ((buf[8] & 0xFF) << 12) 143 + ((buf[9] & 0x3F) << 20); 144 result[3] 145 = ((buf[9] & 0xFF) >> 6) 146 + ((buf[10] & 0xFF) << 2) 147 + ((buf[11] & 0xFF) << 10) 148 + ((buf[12] & 0xFF) << 18); 149 result[4] 150 = (buf[13] & 0xFF) 151 + ((buf[14] & 0xFF) << 8) 152 + ((buf[15] & 0xFF) << 16); 153 154 return result; 155 } 156 157 private static void toByteArray(long v0, long v1, long v2, long v3, 158 long v4, byte[] dst) { 159 160 dst[0] = (byte) v0; 161 v0 >>= 8; 162 dst[1] = (byte) v0; 163 v0 >>= 8; 164 dst[2] = (byte) v0; 165 v0 >>= 8; 166 dst[3] = (byte) v0; 167 168 dst[3] += (v1 & 0x3F) << 2; 169 v1 >>= 6; 170 dst[4] = (byte) v1; 171 v1 >>= 8; 172 dst[5] = (byte) v1; 173 v1 >>= 8; 174 dst[6] = (byte) v1; 175 176 dst[6] += (v2 & 0xF) << 4; 177 v2 >>= 4; 178 dst[7] = (byte) v2; 179 v2 >>= 8; 180 dst[8] = (byte) v2; 181 v2 >>= 8; 182 dst[9] = (byte) v2; 183 184 dst[9] += (v3 & 0x3) << 6; 185 v3 >>= 2; 186 dst[10] = (byte) v3; 187 v3 >>= 8; 188 dst[11] = (byte) v3; 189 v3 >>= 8; 190 dst[12] = (byte) v3; 191 192 dst[13] = (byte) v4; 193 v4 >>= 8; 194 dst[14] = (byte) v4; 195 v4 >>= 8; 196 dst[15] = (byte) v4; 197 } 198 199 protected static long carryValue(long x) { 200 return x >> BITS_PER_LIMB; 201 } 202 203 public static void carryReduce(int[] r, long c0, long c1, long c2, 204 long c3, long c4) { 205 206 long c; 207 208 c = carryValue(c3); c3 &= LIMB_MASK; c4 += c; 209 c = carryValue(c4); c4 &= LIMB_MASK; c0 += c * 5; 210 c = carryValue(c0); c0 &= LIMB_MASK; c1 += c; 211 c = carryValue(c1); c1 &= LIMB_MASK; c2 += c; 212 c = carryValue(c2); c2 &= LIMB_MASK; c3 += c; 213 c = carryValue(c3); c3 &= LIMB_MASK; c4 += c; 214 215 r[0] = (int) c0; 216 r[1] = (int) c1; 217 r[2] = (int) c2; 218 r[3] = (int) c3; 219 r[4] = (int) c4; 220 } 221 222 private int[] multiply(int[] a, int[] b) { 223 int[] result = new int[5]; 224 225 long a0 = a[0]; 226 long a1 = a[1]; 227 long a2 = a[2]; 228 long a3 = a[3]; 229 long a4 = a[4]; 230 231 long c0 = (a0 * b[0]) + 5 * (a1 * b[4]) + 5 * (a2 * b[3]) + 232 5 * (a3 * b[2]) + 5 * (a4 * b[1]); 233 long c1 = (a0 * b[1]) + (a1 * b[0]) + 5 * (a2 * b[4]) + 234 5 * (a3 * b[3]) + 5 * (a4 * b[2]); 235 long c2 = (a0 * b[2]) + (a1 * b[1]) + (a2 * b[0]) + 236 5 * (a3 * b[4]) + 5 * (a4 * b[3]); 237 long c3 = (a0 * b[3]) + (a1 * b[2]) + (a2 * b[1]) + (a3 * b[0]) + 238 5 * (a4 * b[4]); 239 long c4 = (a0 * b[4]) + (a1 * b[3]) + (a2 * b[2]) + (a3 * b[1]) + 240 (a4 * b[0]); 241 242 carryReduce(result, c0, c1, c2, c3, c4); 243 244 return result; 245 } 246 247 private LongVector rPowerVec(int[][] r, long[] temp, int maxIndex, 248 int secondIndex) { 249 250 for (int i = 0; i < temp.length; i++) { 251 temp[i] = r[maxIndex - i][secondIndex]; 252 } 253 return LongVector.fromArray(longSpecies, temp, 0); 254 } 255 256 public void computeTag(byte[] key, byte[] msg, byte[] out) { 257 258 byte[] keyBytes = key.clone(); 259 260 // setup key values 261 // Clamp the bytes in the "r" half of the key. 262 keyBytes[3] &= 15; 263 keyBytes[7] &= 15; 264 keyBytes[11] &= 15; 265 keyBytes[15] &= 15; 266 keyBytes[4] &= 252; 267 keyBytes[8] &= 252; 268 keyBytes[12] &= 252; 269 270 // Create IntegerModuloP elements from the r and s values 271 int[][] r = new int[vectorWidth][]; 272 r[0] = fromByteArray(keyBytes); 273 for (int i = 1; i < vectorWidth; i++) { 274 r[i] = multiply(r[i - 1], r[0]); 275 } 276 277 int rUpIndex = vectorWidth - 1; 278 IntVector rUp0_int = IntVector.broadcast(intSpecies, r[rUpIndex][0]); 279 IntVector rUp1_int = IntVector.broadcast(intSpecies, r[rUpIndex][1]); 280 IntVector rUp2_int = IntVector.broadcast(intSpecies, r[rUpIndex][2]); 281 IntVector rUp3_int = IntVector.broadcast(intSpecies, r[rUpIndex][3]); 282 IntVector rUp4_int = IntVector.broadcast(intSpecies, r[rUpIndex][4]); 283 284 IntVector r5Up1_int = rUp1_int.mul(5); 285 IntVector r5Up2_int = rUp2_int.mul(5); 286 IntVector r5Up3_int = rUp3_int.mul(5); 287 IntVector r5Up4_int = rUp4_int.mul(5); 288 289 LongVector longMsg0 = LongVector.fromByteArray(longSpecies, msg, 0); 290 LongVector longMsg1 = 291 LongVector.fromByteArray(longSpecies, msg, vectorWidth * 8); 292 293 LongVector inAlign0 = 294 longMsg0.rearrange(longMsg1, inShuffle0, inMask); 295 LongVector inAlign1 = 296 longMsg0.rearrange(longMsg1, inShuffle1, inMask); 297 298 IntVector a0 = (IntVector) 299 inAlign0.and(LIMB_MASK).cast(intSpecies); 300 IntVector a1 = (IntVector) 301 inAlign0.shiftR(26).and(LIMB_MASK).cast(intSpecies); 302 IntVector a2 = (IntVector) 303 inAlign0.shiftR(52).and(0xFFF).cast(intSpecies); 304 a2 = a2.or(inAlign1.and(0x3FFF).shiftL(12).cast(intSpecies)); 305 IntVector a3 = (IntVector) 306 inAlign1.shiftR(14).and(LIMB_MASK).cast(intSpecies); 307 IntVector a4 = (IntVector) 308 inAlign1.shiftR(40).and(0xFFFFFF).cast(intSpecies); 309 a4 = a4.or(1 << 24); 310 311 int numParBlocks = msg.length / parBlockCount - 1; 312 for (int i = 0; i < numParBlocks; i++) { 313 314 // multiply and reduce 315 LongVector c0 = (LongVector) 316 a0.cast(longSpecies).mul(rUp0_int.cast(longSpecies)) 317 .add(a1.cast(longSpecies).mul(r5Up4_int.cast(longSpecies))) 318 .add(a2.cast(longSpecies).mul(r5Up3_int.cast(longSpecies))) 319 .add(a3.cast(longSpecies).mul(r5Up2_int.cast(longSpecies))) 320 .add(a4.cast(longSpecies).mul(r5Up1_int.cast(longSpecies))); 321 322 LongVector c1 = (LongVector) 323 a0.cast(longSpecies).mul(rUp1_int.cast(longSpecies)) 324 .add(a1.cast(longSpecies).mul(rUp0_int.cast(longSpecies))) 325 .add(a2.cast(longSpecies).mul(r5Up4_int.cast(longSpecies))) 326 .add(a3.cast(longSpecies).mul(r5Up3_int.cast(longSpecies))) 327 .add(a4.cast(longSpecies).mul(r5Up2_int.cast(longSpecies))); 328 329 LongVector c2 = (LongVector) 330 a0.cast(longSpecies).mul(rUp2_int.cast(longSpecies)) 331 .add(a1.cast(longSpecies).mul(rUp1_int.cast(longSpecies))) 332 .add(a2.cast(longSpecies).mul(rUp0_int.cast(longSpecies))) 333 .add(a3.cast(longSpecies).mul(r5Up4_int.cast(longSpecies))) 334 .add(a4.cast(longSpecies).mul(r5Up3_int.cast(longSpecies))); 335 336 LongVector c3 = (LongVector) 337 a0.cast(longSpecies).mul(rUp3_int.cast(longSpecies)) 338 .add(a1.cast(longSpecies).mul(rUp2_int.cast(longSpecies))) 339 .add(a2.cast(longSpecies).mul(rUp1_int.cast(longSpecies))) 340 .add(a3.cast(longSpecies).mul(rUp0_int.cast(longSpecies))) 341 .add(a4.cast(longSpecies).mul(r5Up4_int.cast(longSpecies))); 342 343 LongVector c4 = (LongVector) 344 a0.cast(longSpecies).mul(rUp4_int.cast(longSpecies)) 345 .add(a1.cast(longSpecies).mul(rUp3_int.cast(longSpecies))) 346 .add(a2.cast(longSpecies).mul(rUp2_int.cast(longSpecies))) 347 .add(a3.cast(longSpecies).mul(rUp1_int.cast(longSpecies))) 348 .add(a4.cast(longSpecies).mul(rUp0_int.cast(longSpecies))); 349 350 // carry/reduce 351 // Note: this carry/reduce sequence might not be correct 352 c4 = c4.add(c3.shiftR(BITS_PER_LIMB)); 353 c3 = c3.and(LIMB_MASK); 354 c0 = c0.add(c4.shiftR(BITS_PER_LIMB).mul(5)); 355 c4 = c4.and(LIMB_MASK); 356 c1 = c1.add(c0.shiftR(BITS_PER_LIMB)); 357 c0 = c0.and(LIMB_MASK); 358 c2 = c2.add(c1.shiftR(BITS_PER_LIMB)); 359 c1 = c1.and(LIMB_MASK); 360 c3 = c3.add(c2.shiftR(BITS_PER_LIMB)); 361 c2 = c2.and(LIMB_MASK); 362 c4 = c4.add(c3.shiftR(BITS_PER_LIMB)); 363 c3 = c3.and(LIMB_MASK); 364 365 a0 = (IntVector) c0.cast(intSpecies); 366 a1 = (IntVector) c1.cast(intSpecies); 367 a2 = (IntVector) c2.cast(intSpecies); 368 a3 = (IntVector) c3.cast(intSpecies); 369 a4 = (IntVector) c4.cast(intSpecies); 370 371 // fromByteArray and add next part of message 372 int start = parBlockCount * (i + 1); 373 374 longMsg0 = LongVector.fromByteArray(longSpecies, msg, start); 375 longMsg1 = LongVector.fromByteArray(longSpecies, msg, 376 start + vectorWidth * 8); 377 378 inAlign0 = longMsg0.rearrange(longMsg1, inShuffle0, inMask); 379 inAlign1 = longMsg0.rearrange(longMsg1, inShuffle1, inMask); 380 381 IntVector in0 = (IntVector) 382 inAlign0.and(LIMB_MASK).cast(intSpecies); 383 IntVector in1 = (IntVector) 384 inAlign0.shiftR(26).and(LIMB_MASK).cast(intSpecies); 385 IntVector in2 = (IntVector) 386 inAlign0.shiftR(52).and(0xFFF).cast(intSpecies); 387 in2 = in2.or(inAlign1.and(0x3FFF).shiftL(12).cast(intSpecies)); 388 IntVector in3 = (IntVector) 389 inAlign1.shiftR(14).and(LIMB_MASK).cast(intSpecies); 390 IntVector in4 = (IntVector) 391 inAlign1.shiftR(40).and(0xFFFFFF).cast(intSpecies); 392 in4 = in4.or(1 << 24); 393 394 a0 = a0.add(in0); 395 a1 = a1.add(in1); 396 a2 = a2.add(in2); 397 a3 = a3.add(in3); 398 a4 = a4.add(in4); 399 } 400 401 // multiply by powers of r 402 long[] rTemp = new long[vectorWidth]; 403 LongVector rFin0 = rPowerVec(r, rTemp, rUpIndex, 0); 404 LongVector rFin1 = rPowerVec(r, rTemp, rUpIndex, 1); 405 LongVector rFin2 = rPowerVec(r, rTemp, rUpIndex, 2); 406 LongVector rFin3 = rPowerVec(r, rTemp, rUpIndex, 3); 407 LongVector rFin4 = rPowerVec(r, rTemp, rUpIndex, 4); 408 409 LongVector r5Fin_1 = rFin1.mul(5); 410 LongVector r5Fin_2 = rFin2.mul(5); 411 LongVector r5Fin_3 = rFin3.mul(5); 412 LongVector r5Fin_4 = rFin4.mul(5); 413 414 LongVector c0 = (LongVector) a0.cast(longSpecies).mul(rFin0) 415 .add(a1.cast(longSpecies).mul(r5Fin_4)) 416 .add(a2.cast(longSpecies).mul(r5Fin_3)) 417 .add(a3.cast(longSpecies).mul(r5Fin_2)) 418 .add(a4.cast(longSpecies).mul(r5Fin_1)); 419 LongVector c1 = (LongVector) a0.cast(longSpecies).mul(rFin1) 420 .add(a1.cast(longSpecies).mul(rFin0)) 421 .add(a2.cast(longSpecies).mul(r5Fin_4)) 422 .add(a3.cast(longSpecies).mul(r5Fin_3)) 423 .add(a4.cast(longSpecies).mul(r5Fin_2)); 424 LongVector c2 = (LongVector) a0.cast(longSpecies).mul(rFin2) 425 .add(a1.cast(longSpecies).mul(rFin1)) 426 .add(a2.cast(longSpecies).mul(rFin0)) 427 .add(a3.cast(longSpecies).mul(r5Fin_4)) 428 .add(a4.cast(longSpecies).mul(r5Fin_3)); 429 LongVector c3 = (LongVector) a0.cast(longSpecies).mul(rFin3) 430 .add(a1.cast(longSpecies).mul(rFin2)) 431 .add(a2.cast(longSpecies).mul(rFin1)) 432 .add(a3.cast(longSpecies).mul(rFin0)) 433 .add(a4.cast(longSpecies).mul(r5Fin_4)); 434 LongVector c4 = (LongVector) a0.cast(longSpecies).mul(rFin4) 435 .add(a1.cast(longSpecies).mul(rFin3)) 436 .add(a2.cast(longSpecies).mul(rFin2)) 437 .add(a3.cast(longSpecies).mul(rFin1)) 438 .add(a4.cast(longSpecies).mul(rFin0)); 439 440 c4 = c4.add(c3.shiftR(BITS_PER_LIMB)); 441 c3 = c3.and(LIMB_MASK); 442 c0 = c0.add(c4.shiftR(BITS_PER_LIMB).mul(5)); 443 c4 = c4.and(LIMB_MASK); 444 c1 = c1.add(c0.shiftR(BITS_PER_LIMB)); 445 c0 = c0.and(LIMB_MASK); 446 c2 = c2.add(c1.shiftR(BITS_PER_LIMB)); 447 c1 = c1.and(LIMB_MASK); 448 c3 = c3.add(c2.shiftR(BITS_PER_LIMB)); 449 c2 = c2.and(LIMB_MASK); 450 c4 = c4.add(c3.shiftR(BITS_PER_LIMB)); 451 c3 = c3.and(LIMB_MASK); 452 453 a0 = (IntVector) c0.cast(intSpecies); 454 a1 = (IntVector) c1.cast(intSpecies); 455 a2 = (IntVector) c2.cast(intSpecies); 456 a3 = (IntVector) c3.cast(intSpecies); 457 a4 = (IntVector) c4.cast(intSpecies); 458 459 // collect lanes and calculate tag 460 long a0Fin = a0.addAll(); 461 long a1Fin = a1.addAll(); 462 long a2Fin = a2.addAll(); 463 long a3Fin = a3.addAll(); 464 long a4Fin = a4.addAll(); 465 466 // carry/reduce the result 467 a4Fin = a4Fin + (a3Fin >>> BITS_PER_LIMB); 468 a3Fin = a3Fin & LIMB_MASK; 469 a0Fin = a0Fin + ((a4Fin >>> BITS_PER_LIMB) * 5); 470 a4Fin = a4Fin & LIMB_MASK; 471 a1Fin = a1Fin + (a0Fin >>> BITS_PER_LIMB); 472 a0Fin = a0Fin & LIMB_MASK; 473 a2Fin = a2Fin + (a1Fin >>> BITS_PER_LIMB); 474 a1Fin = a1Fin & LIMB_MASK; 475 a3Fin = a3Fin + (a2Fin >>> BITS_PER_LIMB); 476 a2Fin = a2Fin & LIMB_MASK; 477 a4Fin = a4Fin + (a3Fin >>> BITS_PER_LIMB); 478 a3Fin = a3Fin & LIMB_MASK; 479 480 byte[] s_arr = 481 Arrays.copyOfRange(keyBytes, RS_LENGTH, 2 * RS_LENGTH); 482 int[] s = fromByteArray(s_arr); 483 484 // Add in the s-half of the key to the accumulator 485 a0Fin += s[0]; 486 a1Fin += s[1]; 487 a2Fin += s[2]; 488 a3Fin += s[3]; 489 a4Fin += s[4]; 490 491 // final carry mod 2^130 492 a1Fin = a1Fin + (a0Fin >> BITS_PER_LIMB); 493 a0Fin = a0Fin & LIMB_MASK; 494 a2Fin = a2Fin + (a1Fin >> BITS_PER_LIMB); 495 a1Fin = a1Fin & LIMB_MASK; 496 a3Fin = a3Fin + (a2Fin >> BITS_PER_LIMB); 497 a2Fin = a2Fin & LIMB_MASK; 498 a4Fin = a4Fin + (a3Fin >> BITS_PER_LIMB); 499 a3Fin = a3Fin & LIMB_MASK; 500 a4Fin = a4Fin & LIMB_MASK; 501 502 // put result in buffer 503 toByteArray(a0Fin, a1Fin, a2Fin, a3Fin, a4Fin, out); 504 } 505 } 506 507 508 private static byte[] hexStringToByteArray(String str) { 509 byte[] result = new byte[str.length() / 2]; 510 for (int i = 0; i < result.length; i++) { 511 result[i] = (byte) Character.digit(str.charAt(2 * i), 16); 512 result[i] <<= 4; 513 result[i] += Character.digit(str.charAt(2 * i + 1), 16); 514 } 515 return result; 516 } 517 518 public static String byteArrayToHexString(byte[] arr) { 519 StringBuilder result = new StringBuilder(); 520 for (int i = 0; i < arr.length; ++i) { 521 byte curVal = arr[i]; 522 result.append(Character.forDigit(curVal >> 4 & 0xF, 16)); 523 result.append(Character.forDigit(curVal & 0xF, 16)); 524 } 525 return result.toString(); 526 } 527 528 private static void kat(Poly1305Vector poly1305, String key, String msg, 529 String expectedTag) { 530 531 kat(poly1305, hexStringToByteArray(key), hexStringToByteArray(msg), 532 hexStringToByteArray(expectedTag)); 533 } 534 535 private static void kat(Poly1305Vector poly1305, byte[] key, byte[] msg, 536 byte[] expectedTag) { 537 538 byte[] tag = new byte[expectedTag.length]; 539 poly1305.computeTag(key, msg, tag); 540 if (!Arrays.equals(tag, expectedTag)) { 541 throw new RuntimeException( 542 "bad tag: " + byteArrayToHexString(tag) + 543 " expected: " + byteArrayToHexString(expectedTag)); 544 } 545 } 546 547 /* 548 * Poly1305 Known Answer Tests to ensure that the implementation is correct. 549 */ 550 private static void runKAT(Poly1305Vector poly1305) { 551 kat(poly1305, 552 "d212b886dd4682a41f1759e6c5aef84760e5a63d4423ca7d1fb5c7ecfc5dac27", 553 "5d2ad39e2a7b0bc5f375488643acf391188d01ad936971457427bc053c4262a1" + 554 "598532850def8573213c5f79fa736703c57c03ec49b55617210998c8af408698" + 555 "866632a7ecf7e9a688605cbca919e17e2badd090a7a6d83ad90be0617fa44642" + 556 "cc9a1ca38514a026cbea51c287ec0b56719fc61183c88e9450ba85aa8ab7d390", 557 "7ccdfa8e82df540276e8172f705adce2"); 558 559 kat(poly1305, 560 "2b0b684c86910104aee1d261ac4d5a0f5443b4b7746cf7f8ba03921d273f6a9b", 561 "027b359f44a5d60f81073ceb74749207742529dcefa4a26a1817db2c8d50ba2b" + 562 "d9e170cd1930946872d95e4eae41389f362087871a749897e0fbe42494e6f0b3" + 563 "8db01e2059510b6fda4f422ce7d226433ba00940e1761baaff80d9b8f3a61d11" + 564 "a109e6082d231cf85aa718199e6eaaaf07bad562469ef1b8e639c727967bf6da" + 565 "bcd16fcb0fc102095325e2fac92e599e81c26900df1deb7b0a0b5c321a658024" + 566 "26506740509ece646fecf33a517b66e57577372156aae85765c6b473521d1019" + 567 "4f5fbe0e932cfee716e1d41c9154fb8e15b82ab7e807fb54f3d7d3e4c589cc9a" + 568 "492d17ea4fd27894fa9d22a9db6d5df674cd1e97e7e8758a360291f22dfe1cc3", 569 "84ca3a778faf0ab9f840fe5fb38ace27"); 570 571 kat(poly1305, 572 "870c6fa7da2eadb845ac8b0eeaed4cf856eca67bf96b64a29a2e6a881821fa8a", 573 "ff1a3b67a4f575be5f05c4054e4c7365838c2cbe786ba78900c8b43f197c3c4d" + 574 "120432a287e434669af579bcd56f3320e54d2f97a306f917f2f41b1c97cc69db" + 575 "4ac2051adccd687fa89f92504d1ab5c3006681d846c8051aabccca0024ef5ec4" + 576 "c43b8701ffc9d14fef8d55e229ed210a2b9bde996f5d7b545d15e1fc32764604" + 577 "b2a0384dd173aa800b7526c8ff397c05130bb6a1f2194968adaef6979b023cd8" + 578 "d9195d2739351c7e4ac6c43508634f813641f669e78cbcf732ccb1321a2cd2c4" + 579 "14c7df5b9ea3408f2e12fbf3a3cbdb98699dd5402725ec25f9fff9bcd0f93cb3" + 580 "cf0dac016fec41a5ef3ae8b8d258a09f530ad14ad2e52186041592eac0ea22ff" + 581 "8c3751009b516c60f7764cccbb816394ef035bd8cb2a38d5c6b9229e528e56cd" + 582 "62600b5219b64212642384e628f01d790eeef4963a7d1a63a9faff79d4acfa09" + 583 "78b58b0b623ae89389661aa408b16814d3baaca20978dce6888c3365f4ffd2fa" + 584 "8f031a44f2e870a06da21d7becf450d335e1386268bc189435e7955a477bc368", 585 "ff4e0ee6feb1c6a57e638a79fafc7c60"); 586 587 kat(poly1305, 588 "c27987ae88a833ae2ea90371b2e257c15773da3bc34516b6b075446e1f844a81", 589 "64e5a2e2940b173c7103ae931ced302a8f8c778f4e5c0b3677c51552655005d8" + 590 "504b724107e7262448c94db83fc9c6a2a26fc973360dce15c0553b73bb733d3e" + 591 "f61fcba8977e76c32523b80c3b45b1226b23ee17522f9b677880c69b356917ae" + 592 "3c792a0c5b0c77b90dfa51483626323b7a73fffb1b128c595d553bf62a8f5bb9" + 593 "fa48b4a850a932481bf607e8da84730c9052bba9316ec7eb84007a4eb5cbed5c" + 594 "7c67ef32d4c5cb6cfbccd738d239857c240de6d3d4e5af14d480feb63541e5d8" + 595 "036e088b2e32431e6fe0c4d3505aebe2e14bd02b6b15325f89aef048cd1236db" + 596 "4461a59304b7c61ece2c52ef8ac4cf2326e6aaff013494b1b191be4ae4381f57" + 597 "e72b947ee23d0a528087db9338bc28c68484929fc3436995b2083b06a765ceb7" + 598 "09e9dd41ba896d99832d6851189766e844137d9a83d2890bc2be7afc82f9ebb8" + 599 "bafe08ef5f7ff0cce9a1d08e6b797a17df04731f384a34b16e72e9f2ab070114" + 600 "8008945509fe378658dc51eb752248f48364be327cd1b6bd148c518a976ae95d" + 601 "d391f3b0d447251988c7e77400c9d44395b8f9f10cbc442a6804d0ad83e8c3e3" + 602 "9fa09c2140fac143c90f09a7d907c57e29b528d54c8bd927f39aee2cec671213" + 603 "c50fe657b29682d57a419e3e52dafb348cbe44b6c17e4be18f5c5e411734fcfc" + 604 "99b9ca26f29a21cc93374ef1bfa86ca2bb3be76b94b4ef69ec790c968a51e4d0", 605 "d4c09727f68fa3beb57ce9e74205b652"); 606 607 kat(poly1305, 608 "2593adf2efc0e49c7fde0d45de4f7a21ceb76df45c0e5a917ef1f6b7fbf4fb7e", 609 "23665b9a6d4f04c9d58347d32d64d4cbf8d4ca993a8bb73758e6eb2db9f97096" + 610 "d0f00aca8cb16460d2bc15c0136fa92482602f47b3ec78244c4dc619d9b28afa" + 611 "19b063c196bcff848eff179102cce29dfcc58bf90a2f6311e6d021e2573ccbb4" + 612 "4e06947167c9865127c0b7362196523f97c8157058f7aebff475f77e23393dc1" + 613 "a3031bbaf31270db3eadc00cca6ae073aa53160d095afdce0a202de8a23d9a38" + 614 "b0bed20cbe64e1ec77fc13ba0cfc9be52edb70475bf1aeaaff25e11f2e0ae47f" + 615 "f23cbd4a6219d276fcc6c8f12a739f11434c86d4e24397f96ef6e36d9195fa8a" + 616 "48eb55990d69feacfb754b5019a3ebafa98d5544077b46c136cc11de8ee7f8a6" + 617 "76a6696600088696233f4e8f060ba8a64890fb638469639bfb727ed758c36250" + 618 "a553b7ce1115509f2bb19c13cea87003a8eff45ce9e1cff0a21ba5ae19226d50" + 619 "e108db212a588e5f4c502468859b9b607922c3311b5d912bd9400e696d7debbb" + 620 "9ac5454cc7d0f95fc242c491f095a02f0d3bd7ead0f0b7358c9b1d85e4e9ab75" + 621 "24bb43867c94a21a4e0db6470a210c9dd937e4801396bd687127fa7c83014c85" + 622 "372553c56dfd6cd9b75fa10483aea825f8e3fa53c6bf17467e37c2e7439ed0ea" + 623 "6fb24d13d428965c44f1ac943c7bc77fa84711c91b41f5ee6d9a7d9091648a96" + 624 "cc7c261d7fc5d964446d1e3dcc41d32ecaa8d7791b8462563fcf7f96cd1d11d4" + 625 "34923e0150321356866f5bdafebc96f2661bfd3c1f104e96b6492cafcbe25fc6" + 626 "ec0c92a3bbec7328e1905d5951fae04625a2452f596027a5d9c64eed55165c8a" + 627 "23bc3f944b4fa9c7ad83ebc1777c7153d5de13d04c0a12e774b17906a62f5134" + 628 "685c2de31da08bd04840299fd62d56ffe95248365034e7ba95961cebf0542b24", 629 "b9f68b0996caf5135136b10b37fe5f81"); 630 631 kat(poly1305, 632 "e9c8c78bc0ad5751f094fd4657fe5ef2a3c232f6930eef3431cde76659f04210", 633 "914e57a2745fd475d7b8f982483fe11a05d7b55853239112d5ae99616c718b3c" + 634 "4a0c2d05e3ca1df509614c0fe051b414d404149ec422e0998e192e51518518c4" + 635 "b8acd9e3e3ff9f3b4ef931d3052755785d38e75821ceefa7da0bfe3f1fb2dc6d" + 636 "738e2a2332e53ce77d44547621bb7aa724dd8805c7c795088db865d6b13d9b3e" + 637 "8acec846efb072d105ab6e599f8292a7601087e0ba13af9f503dcfd426e26e4d" + 638 "fb22bf5a1ff1a82d67d9bd8871e6adc17aa39d221f2865f81da9ed566192c269" + 639 "3c85f0442924e603b9ae54b88dd0f21e92eedc40c08dd484c552e297894eeee8" + 640 "b5acc91d5ae16f56257bb0836b48e1a8fa72e83a8b10b7026a7f466c8b08eac5" + 641 "4359b70e639117cf688e263b891f004db94d77941380f3ab0559538c9398c859" + 642 "b76d2bbcd6b635e753160583e7adc263097a80520d003514e134a21597c1ec57" + 643 "55da3a70acc6951b4d4d81e98b9eb962d9e3bc37d5e8ebd61e2a3f61cc452a65" + 644 "56571e12c190d4e3d0f8cc61ffcb60324b4a6987e7375a832ff807682e0b4595" + 645 "66ef1f765638f3d2e837ed43ce2c1c7837f271c866908d865c3d9174fd4f8056" + 646 "265abfb88fbc207db7a12c0a0ad035e5a728725e98cb682d41fd0bcf3aef2fd7" + 647 "ab261727f310fc7cf3b34286c9e9ee235995315167191f3b4d77e5642fb57dbd" + 648 "fdb5ccadefc5d03866918ab1a3eff54b405d8946e2b0c2fa444d1b2be4c3d41d" + 649 "990515e7534190d66d10e38c36c5d3df0315db85ba10c924bef97d1faa07a5f8" + 650 "f04998a7d38689237a1912bea3f821357d8383d7c5cfa66ba5965b5a94bb702c" + 651 "e6583e59879021139355c5b90e0f9cd13b34f3357ffde404bbf34c97f9fd55b5" + 652 "53e42d8a6b370eded02c8a5221e15db701da56918412520e12fd1ef9f4748647" + 653 "858488d5e0abd5b9e01457768907e1d24581f9591771304192711292e4025fce" + 654 "bd92adb2297e9496852f80bd78578bbdb292ca209f7584ff76e9eb66ec8a111e" + 655 "add30dc7ef364c4f1339312f226fe0cfa7a5b1602417e469cf2c8e3874c51232" + 656 "00f2d90dbe7f3c3ff5c6c6484052a80eb6229a6ed6176ad600da185da624bea6", 657 "c1de44dd8ea245ca43e5587460feb514"); 658 } 659 }