Beispiel #1
0
async def test_prefetched_sad_not_twice(aiohttp_client):
    client, auth_man, csc_dummy = await _set_up_dummy_client(
        aiohttp_client, require_hash_pinning=False)

    # prefetch SAD that is not bound to any hashes
    async with client.post('/csc/v1/credentials/authorize',
                           json=auth_man.format_csc_auth_request(),
                           raise_for_status=True) as resp:
        sad = (await resp.json())['SAD']
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=auth_man.csc_session_info,
        credential_info=auth_man.credential_info,
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=sad))

    signer = csc_signer.CSCSigner(
        session=client,
        auth_manager=auth_man,
        batch_autocommit=True,
        batch_size=1,
    )

    result = await signer.async_sign_raw(b'foobar', digest_algorithm='sha256')
    signer_cert = TESTING_CA.get_cert(CertLabel('signer1'))
    _validate_raw(result,
                  b'foobar',
                  signer_cert,
                  signature_algorithm=algos.SignedDigestAlgorithm(
                      {'algorithm': 'sha256_rsa'}),
                  md_algorithm='sha256')

    # but a second attempt should fail
    with pytest.raises(SigningError, match='No signing results'):
        await signer.async_sign_raw(b'foobar', digest_algorithm='sha256')
Beispiel #2
0
async def test_sign_unreadable_sig(aiohttp_client, response_obj):
    csc_session_info = csc_signer.CSCServiceSessionInfo('', 'foobar')
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_session_info,
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset({'sha256_rsa'}),
            max_batch_size=1,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))

    async def fake_return(_request):
        return web.json_response(response_obj)

    app = web.Application()
    app.router.add_post('/csc/v1/signatures/signHash', fake_return)
    client = await aiohttp_client(app)
    signer = csc_signer.CSCSigner(
        client,
        auth_manager=auth_man,
        batch_size=1,
        batch_autocommit=False,
        client_data='Some client data, because why not')
    result = asyncio.create_task(signer.async_sign_raw(b'foobarbaz', 'sha256'))
    with pytest.raises(SigningError, match='Expected response with b64'):
        await asyncio.sleep(1)
        await signer.commit()

    try:
        result.cancel()
        await result
    except asyncio.CancelledError:
        pass
Beispiel #3
0
async def test_sign_mechanism_not_supported():
    csc_session_info = csc_signer.CSCServiceSessionInfo(
        'https://example.com', 'foobar')
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_session_info,
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset({'is_nonsense'}),
            max_batch_size=10,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))
    # check expected failure for a signing attempt
    with pytest.raises(SigningError, match='No signing results available'):
        async with aiohttp.ClientSession() as session:
            signer = csc_signer.CSCSigner(session, auth_manager=auth_man)
            await signer.async_sign_raw(b'foobarbazquux', 'sha256')

    # check expected failure when fetching the signature mechanism directly
    with pytest.raises(SigningError, match='must be one of'):
        # noinspection PyTypeChecker
        signer = csc_signer.CSCSigner(None, auth_manager=auth_man)
        signer.get_signature_mechanism(digest_algorithm='sha256')

    # ...but overrides should still work
    # noinspection PyTypeChecker
    signer = csc_signer.CSCSigner(None, auth_manager=auth_man)
    signer.signature_mechanism = mech \
        = algos.SignedDigestAlgorithm({'algorithm': 'sha256_rsa'})
    assert signer.get_signature_mechanism(digest_algorithm='sha256') == mech
Beispiel #4
0
async def test_csc_placeholder_sig_size():

    csc_session_info = csc_signer.CSCServiceSessionInfo(
        'https://example.com', 'foobar')
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_session_info,
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset({'is_nonsense'}),
            max_batch_size=10,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))
    # noinspection PyTypeChecker
    signer = csc_signer.CSCSigner(None, auth_manager=auth_man)
    await signer.async_sign_raw(b'foobarbazquux', 'sha256', dry_run=True)
Beispiel #5
0
async def test_sign_network_fail():
    csc_session_info = csc_signer.CSCServiceSessionInfo(
        'https://example.invalid', 'foobar')
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_session_info,
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset({'sha256_rsa'}),
            max_batch_size=10,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))

    with pytest.raises(SigningError, match='No signing results available'):
        async with aiohttp.ClientSession() as session:
            signer = csc_signer.CSCSigner(session, auth_manager=auth_man)
            await signer.async_sign_raw(b'foobarbazquux', 'sha256')
Beispiel #6
0
async def test_fail_different_digest():
    csc_session_info = csc_signer.CSCServiceSessionInfo('', 'foobar')
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_session_info,
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset({'sha256_rsa'}),
            max_batch_size=2,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))
    # noinspection PyTypeChecker
    signer = csc_signer.CSCSigner(None, auth_manager=auth_man, batch_size=2)
    with pytest.raises(SigningError, match='same digest function'):
        result = asyncio.gather(
            signer.async_sign_raw(b'foobarbaz', 'sha256'),
            signer.async_sign_raw(b'foobarbazquux', 'sha512'),
        )
        await result
Beispiel #7
0
def test_format_csc_auth_request():
    # any old auth manager will do
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_signer.CSCServiceSessionInfo(
            'https://example.com', 'foobar'),
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset(),
            max_batch_size=10,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))
    result = auth_man.format_csc_auth_request(
        pin='1234',
        otp='123456',
        hash_b64s=[
            'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM=',
            'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM='
        ],
        description='baz',
        client_data='quux')
    assert result == {
        'credentialID':
        'foobar',
        'numSignatures':
        2,
        'hash': [
            'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM=',
            'Sa6Tcy/PjWP+HM51lmSYLb1bIxYfAH26hWGGKtyW0GM='
        ],
        'PIN':
        '1234',
        'OTP':
        '123456',
        'description':
        'baz',
        'clientData':
        'quux'
    }
Beispiel #8
0
async def test_sign_wrong_number_of_sigs(aiohttp_client):
    csc_session_info = csc_signer.CSCServiceSessionInfo('', 'foobar')
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=csc_session_info,
        credential_info=csc_signer.CSCCredentialInfo(
            signing_cert=TESTING_CA.get_cert(CertLabel('signer1')),
            chain=[],
            supported_mechanisms=frozenset({'sha256_rsa'}),
            max_batch_size=2,
            hash_pinning_required=False,
            response_data={}),
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))

    async def fake_return(_request):
        return web.json_response(
            {'signatures': [
                base64.b64encode(bytes(512)).decode('ascii'),
            ]})

    app = web.Application()
    app.router.add_post('/csc/v1/signatures/signHash', fake_return)
    client = await aiohttp_client(app)
    signer = csc_signer.CSCSigner(client,
                                  auth_manager=auth_man,
                                  batch_size=2,
                                  batch_autocommit=False)
    result = asyncio.gather(
        signer.async_sign_raw(b'foobarbaz', 'sha256'),
        signer.async_sign_raw(b'foobarbazquux', 'sha256'),
    )

    with pytest.raises(SigningError, match='Expected 2 signatures'):
        await asyncio.sleep(1)
        await signer.commit()
    try:
        result.cancel()
        await result
    except asyncio.CancelledError:
        pass
Beispiel #9
0
async def test_multi_commit_failure(aiohttp_client):

    client, auth_man, csc_dummy = await _set_up_dummy_client(aiohttp_client)
    # deliberately pass a bogus SAD to make the commit fail
    auth_man = csc_signer.PrefetchedSADAuthorizationManager(
        csc_session_info=auth_man.csc_session_info,
        credential_info=auth_man.credential_info,
        csc_auth_info=csc_signer.CSCAuthorizationInfo(sad=''))

    class SlowCommitter(csc_signer.CSCSigner):
        async def _do_commit(self, batch):
            # waste time
            await asyncio.sleep(3)
            await super()._do_commit(batch)

    signer = SlowCommitter(session=client,
                           auth_manager=auth_man,
                           batch_autocommit=False,
                           batch_size=1)

    async def produce_signature():
        result = asyncio.create_task(
            signer.async_sign_raw(b'foobar', 'sha256'), )
        await asyncio.sleep(1)
        with pytest.raises(SigningError, match='Signature request failed'):
            await signer.commit()
        with pytest.raises(SigningError, match='No signing results'):
            return await result

    async def commit_again():
        with pytest.raises(SigningError, match='Commit failed'):
            await asyncio.sleep(2)
            await signer.commit()

    await asyncio.gather(produce_signature(), commit_again())
    # this should now return immediately as there is no batch
    await signer.commit()