Make WordPress Core


Ignore:
Timestamp:
12/09/2019 04:44:58 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.
Merges [46858] to the 5.3 branch.
Fixes #48371.

Location:
branches/5.3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/5.3

  • branches/5.3/src/wp-includes/sodium_compat/src/Crypto32.php

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