Make WordPress Core


Ignore:
Timestamp:
12/09/2019 04:40:11 PM (5 years ago)
Author:
SergeyBiryukov
Message:

Upgrade/Install: Update sodium_compat to v1.12.1.

This includes a speedup for signature verification on most platforms and bugfixes for 32-bit platforms.

Props paragoninitiativeenterprises, lukaswaudentio.
Fixes #48371.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/sodium_compat/src/Crypto.php

    r46586 r46858  
    779779
    780780    /**
     781     * Initialize a hashing context for BLAKE2b.
     782     *
     783     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     784     *
     785     * @param string $key
     786     * @param int $outputLength
     787     * @param string $salt
     788     * @param string $personal
     789     * @return string
     790     * @throws RangeException
     791     * @throws SodiumException
     792     * @throws TypeError
     793     */
     794    public static function generichash_init_salt_personal(
     795        $key = '',
     796        $outputLength = 32,
     797        $salt = '',
     798        $personal = ''
     799    ) {
     800        // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
     801        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
     802
     803        $k = null;
     804        if (!empty($key)) {
     805            $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
     806            if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
     807                throw new RangeException('Invalid key size');
     808            }
     809        }
     810        if (!empty($salt)) {
     811            $s = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt);
     812        } else {
     813            $s = null;
     814        }
     815        if (!empty($salt)) {
     816            $p = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal);
     817        } else {
     818            $p = null;
     819        }
     820
     821        /** @var SplFixedArray $ctx */
     822        $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s, $p);
     823
     824        return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
     825    }
     826
     827    /**
    781828     * Update a hashing context for BLAKE2b with $message
    782829     *
     
    11871234
    11881235    /**
     1236     * @param string $key
     1237     * @return array<int, string> Returns a state and a header.
     1238     * @throws Exception
     1239     * @throws SodiumException
     1240     */
     1241    public static function secretstream_xchacha20poly1305_init_push($key)
     1242    {
     1243        # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
     1244        $out = random_bytes(24);
     1245
     1246        # crypto_core_hchacha20(state->k, out, k, NULL);
     1247        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20($out, $key);
     1248        $state = new ParagonIE_Sodium_Core_SecretStream_State(
     1249            $subkey,
     1250            ParagonIE_Sodium_Core_Util::substr($out, 16, 8) . str_repeat("\0", 4)
     1251        );
     1252
     1253        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
     1254        $state->counterReset();
     1255
     1256        # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
     1257        #        crypto_secretstream_xchacha20poly1305_INONCEBYTES);
     1258        # memset(state->_pad, 0, sizeof state->_pad);
     1259        return array(
     1260            $state->toString(),
     1261            $out
     1262        );
     1263    }
     1264
     1265    /**
     1266     * @param string $key
     1267     * @param string $header
     1268     * @return string Returns a state.
     1269     * @throws Exception
     1270     */
     1271    public static function secretstream_xchacha20poly1305_init_pull($key, $header)
     1272    {
     1273        # crypto_core_hchacha20(state->k, in, k, NULL);
     1274        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
     1275            ParagonIE_Sodium_Core_Util::substr($header, 0, 16),
     1276            $key
     1277        );
     1278        $state = new ParagonIE_Sodium_Core_SecretStream_State(
     1279            $subkey,
     1280            ParagonIE_Sodium_Core_Util::substr($header, 16)
     1281        );
     1282        $state->counterReset();
     1283        # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
     1284        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
     1285        # memset(state->_pad, 0, sizeof state->_pad);
     1286        # return 0;
     1287        return $state->toString();
     1288    }
     1289
     1290    /**
     1291     * @param string $state
     1292     * @param string $msg
     1293     * @param string $aad
     1294     * @param int $tag
     1295     * @return string
     1296     * @throws SodiumException
     1297     */
     1298    public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0)
     1299    {
     1300        $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
     1301        # crypto_onetimeauth_poly1305_state poly1305_state;
     1302        # unsigned char                     block[64U];
     1303        # unsigned char                     slen[8U];
     1304        # unsigned char                    *c;
     1305        # unsigned char                    *mac;
     1306
     1307        $msglen = ParagonIE_Sodium_Core_Util::strlen($msg);
     1308        $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad);
     1309
     1310        if ((($msglen + 63) >> 6) > 0xfffffffe) {
     1311            throw new SodiumException(
     1312                'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
     1313            );
     1314        }
     1315
     1316        # if (outlen_p != NULL) {
     1317        #     *outlen_p = 0U;
     1318        # }
     1319        # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
     1320        #     sodium_misuse();
     1321        # }
     1322
     1323        # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
     1324        # crypto_onetimeauth_poly1305_init(&poly1305_state, block);
     1325        # sodium_memzero(block, sizeof block);
     1326        $auth = new ParagonIE_Sodium_Core_Poly1305_State(
     1327            ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
     1328        );
     1329
     1330        # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
     1331        $auth->update($aad);
     1332
     1333        # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
     1334        #     (0x10 - adlen) & 0xf);
     1335        $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));
     1336
     1337        # memset(block, 0, sizeof block);
     1338        # block[0] = tag;
     1339        # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
     1340        #                                    state->nonce, 1U, state->k);
     1341        $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
     1342            ParagonIE_Sodium_Core_Util::intToChr($tag) . str_repeat("\0", 63),
     1343            $st->getCombinedNonce(),
     1344            $st->getKey(),
     1345            ParagonIE_Sodium_Core_Util::store64_le(1)
     1346        );
     1347
     1348        # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
     1349        $auth->update($block);
     1350
     1351        # out[0] = block[0];
     1352        $out = $block[0];
     1353        # c = out + (sizeof tag);
     1354        # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
     1355        $cipher = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
     1356            $msg,
     1357            $st->getCombinedNonce(),
     1358            $st->getKey(),
     1359            ParagonIE_Sodium_Core_Util::store64_le(2)
     1360        );
     1361
     1362        # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
     1363        $auth->update($cipher);
     1364
     1365        $out .= $cipher;
     1366        unset($cipher);
     1367
     1368        # crypto_onetimeauth_poly1305_update
     1369        # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
     1370        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));
     1371
     1372        # STORE64_LE(slen, (uint64_t) adlen);
     1373        $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen);
     1374
     1375        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
     1376        $auth->update($slen);
     1377
     1378        # STORE64_LE(slen, (sizeof block) + mlen);
     1379        $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen);
     1380
     1381        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
     1382        $auth->update($slen);
     1383
     1384        # mac = c + mlen;
     1385        # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
     1386        $mac = $auth->finish();
     1387        $out .= $mac;
     1388
     1389        # sodium_memzero(&poly1305_state, sizeof poly1305_state);
     1390        unset($auth);
     1391
     1392
     1393        # XOR_BUF(STATE_INONCE(state), mac,
     1394        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
     1395        $st->xorNonce($mac);
     1396
     1397        # sodium_increment(STATE_COUNTER(state),
     1398        #     crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
     1399        $st->incrementCounter();
     1400        // Overwrite by reference:
     1401        $state = $st->toString();
     1402
     1403        /** @var bool $rekey */
     1404        $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
     1405        # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
     1406        #     sodium_is_zero(STATE_COUNTER(state),
     1407        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
     1408        #     crypto_secretstream_xchacha20poly1305_rekey(state);
     1409        # }
     1410        if ($rekey || $st->needsRekey()) {
     1411            // DO REKEY
     1412            self::secretstream_xchacha20poly1305_rekey($state);
     1413        }
     1414        # if (outlen_p != NULL) {
     1415        #     *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
     1416        # }
     1417        return $out;
     1418    }
     1419
     1420    /**
     1421     * @param string $state
     1422     * @param string $cipher
     1423     * @param string $aad
     1424     * @return bool|array{0: string, 1: int}
     1425     * @throws SodiumException
     1426     */
     1427    public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '')
     1428    {
     1429        $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
     1430
     1431        $cipherlen = ParagonIE_Sodium_Core_Util::strlen($cipher);
     1432        #     mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
     1433        $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
     1434        $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad);
     1435
     1436        #     if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
     1437        #         sodium_misuse();
     1438        #     }
     1439        if ((($msglen + 63) >> 6) > 0xfffffffe) {
     1440            throw new SodiumException(
     1441                'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
     1442            );
     1443        }
     1444
     1445        #     crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
     1446        #     crypto_onetimeauth_poly1305_init(&poly1305_state, block);
     1447        #     sodium_memzero(block, sizeof block);
     1448        $auth = new ParagonIE_Sodium_Core_Poly1305_State(
     1449            ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
     1450        );
     1451
     1452        #     crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
     1453        $auth->update($aad);
     1454
     1455        #     crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
     1456        #         (0x10 - adlen) & 0xf);
     1457        $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));
     1458
     1459
     1460        #     memset(block, 0, sizeof block);
     1461        #     block[0] = in[0];
     1462        #     crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
     1463        #                                        state->nonce, 1U, state->k);
     1464        $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
     1465            $cipher[0] . str_repeat("\0", 63),
     1466            $st->getCombinedNonce(),
     1467            $st->getKey(),
     1468            ParagonIE_Sodium_Core_Util::store64_le(1)
     1469        );
     1470        #     tag = block[0];
     1471        #     block[0] = in[0];
     1472        #     crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
     1473        $tag = ParagonIE_Sodium_Core_Util::chrToInt($block[0]);
     1474        $block[0] = $cipher[0];
     1475        $auth->update($block);
     1476
     1477
     1478        #     c = in + (sizeof tag);
     1479        #     crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
     1480        $auth->update(ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen));
     1481
     1482        #     crypto_onetimeauth_poly1305_update
     1483        #     (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
     1484        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));
     1485
     1486        #     STORE64_LE(slen, (uint64_t) adlen);
     1487        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
     1488        $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen);
     1489        $auth->update($slen);
     1490
     1491        #     STORE64_LE(slen, (sizeof block) + mlen);
     1492        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
     1493        $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen);
     1494        $auth->update($slen);
     1495
     1496        #     crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
     1497        #     sodium_memzero(&poly1305_state, sizeof poly1305_state);
     1498        $mac = $auth->finish();
     1499
     1500        #     stored_mac = c + mlen;
     1501        #     if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
     1502        #     sodium_memzero(mac, sizeof mac);
     1503        #         return -1;
     1504        #     }
     1505
     1506        $stored = ParagonIE_Sodium_Core_Util::substr($cipher, $msglen + 1, 16);
     1507        if (!ParagonIE_Sodium_Core_Util::hashEquals($mac, $stored)) {
     1508            return false;
     1509        }
     1510
     1511        #     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
     1512        $out = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
     1513            ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen),
     1514            $st->getCombinedNonce(),
     1515            $st->getKey(),
     1516            ParagonIE_Sodium_Core_Util::store64_le(2)
     1517        );
     1518
     1519        #     XOR_BUF(STATE_INONCE(state), mac,
     1520        #         crypto_secretstream_xchacha20poly1305_INONCEBYTES);
     1521        $st->xorNonce($mac);
     1522
     1523        #     sodium_increment(STATE_COUNTER(state),
     1524        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
     1525        $st->incrementCounter();
     1526
     1527        #     if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
     1528        #         sodium_is_zero(STATE_COUNTER(state),
     1529        #             crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
     1530        #         crypto_secretstream_xchacha20poly1305_rekey(state);
     1531        #     }
     1532
     1533        // Overwrite by reference:
     1534        $state = $st->toString();
     1535
     1536        /** @var bool $rekey */
     1537        $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
     1538        if ($rekey || $st->needsRekey()) {
     1539            // DO REKEY
     1540            self::secretstream_xchacha20poly1305_rekey($state);
     1541        }
     1542        return array($out, $tag);
     1543    }
     1544
     1545    /**
     1546     * @param string $state
     1547     * @return void
     1548     * @throws SodiumException
     1549     */
     1550    public static function secretstream_xchacha20poly1305_rekey(&$state)
     1551    {
     1552        $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
     1553        # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
     1554        # crypto_secretstream_xchacha20poly1305_INONCEBYTES];
     1555        # size_t        i;
     1556        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
     1557        #     new_key_and_inonce[i] = state->k[i];
     1558        # }
     1559        $new_key_and_inonce = $st->getKey();
     1560
     1561        # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
     1562        #     new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
     1563        #         STATE_INONCE(state)[i];
     1564        # }
     1565        $new_key_and_inonce .= ParagonIE_Sodium_Core_Util::substR($st->getNonce(), 0, 8);
     1566
     1567        # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
     1568        #                                 sizeof new_key_and_inonce,
     1569        #                                 state->nonce, state->k);
     1570
     1571        $st->rekey(ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
     1572            $new_key_and_inonce,
     1573            $st->getCombinedNonce(),
     1574            $st->getKey(),
     1575            ParagonIE_Sodium_Core_Util::store64_le(0)
     1576        ));
     1577
     1578        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
     1579        #     state->k[i] = new_key_and_inonce[i];
     1580        # }
     1581        # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
     1582        #     STATE_INONCE(state)[i] =
     1583        #          new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i];
     1584        # }
     1585        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
     1586        $st->counterReset();
     1587
     1588        $state = $st->toString();
     1589    }
     1590
     1591    /**
    11891592     * Detached Ed25519 signature.
    11901593     *
Note: See TracChangeset for help on using the changeset viewer.