aboutsummaryrefslogtreecommitdiffstats
path: root/tests/hazmat/primitives/test_hash_vectors.py
blob: ca97fc111511424a87a6d941c8e2f95a3c4d1780 (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import absolute_import, division, print_function

import os

import pytest

from cryptography.hazmat.primitives import hashes

from .utils import generate_hash_test, generate_long_string_hash_test
from ...utils import load_hash_vectors


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.SHA1()),
    skip_message="Does not support SHA1",
)
@pytest.mark.hash
class TestSHA1(object):
    test_SHA1 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "SHA1"),
        [
            "SHA1LongMsg.rsp",
            "SHA1ShortMsg.rsp",
        ],
        hashes.SHA1(),
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.SHA224()),
    skip_message="Does not support SHA224",
)
@pytest.mark.hash
class TestSHA224(object):
    test_SHA224 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "SHA2"),
        [
            "SHA224LongMsg.rsp",
            "SHA224ShortMsg.rsp",
        ],
        hashes.SHA224(),
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.SHA256()),
    skip_message="Does not support SHA256",
)
@pytest.mark.hash
class TestSHA256(object):
    test_SHA256 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "SHA2"),
        [
            "SHA256LongMsg.rsp",
            "SHA256ShortMsg.rsp",
        ],
        hashes.SHA256(),
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.SHA384()),
    skip_message="Does not support SHA384",
)
@pytest.mark.hash
class TestSHA384(object):
    test_SHA384 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "SHA2"),
        [
            "SHA384LongMsg.rsp",
            "SHA384ShortMsg.rsp",
        ],
        hashes.SHA384(),
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
    skip_message="Does not support SHA512",
)
@pytest.mark.hash
class TestSHA512(object):
    test_SHA512 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "SHA2"),
        [
            "SHA512LongMsg.rsp",
            "SHA512ShortMsg.rsp",
        ],
        hashes.SHA512(),
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160()),
    skip_message="Does not support RIPEMD160",
)
@pytest.mark.hash
class TestRIPEMD160(object):
    test_RIPEMD160 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "ripemd160"),
        [
            "ripevectors.txt",
        ],
        hashes.RIPEMD160(),
    )

    test_RIPEMD160_long_string = generate_long_string_hash_test(
        hashes.RIPEMD160(),
        "52783243c1697bdbe16d37f97f68f08325dc1528",
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.Whirlpool()),
    skip_message="Does not support Whirlpool",
)
@pytest.mark.hash
class TestWhirlpool(object):
    test_whirlpool = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "whirlpool"),
        [
            "iso-test-vectors.txt",
        ],
        hashes.Whirlpool(),
    )

    test_whirlpool_long_string = generate_long_string_hash_test(
        hashes.Whirlpool(),
        ("0c99005beb57eff50a7cf005560ddf5d29057fd86b2"
         "0bfd62deca0f1ccea4af51fc15490eddc47af32bb2b"
         "66c34ff9ad8c6008ad677f77126953b226e4ed8b01"),
    )


@pytest.mark.supported(
    only_if=lambda backend: backend.hash_supported(hashes.MD5()),
    skip_message="Does not support MD5",
)
@pytest.mark.hash
class TestMD5(object):
    test_md5 = generate_hash_test(
        load_hash_vectors,
        os.path.join("hashes", "MD5"),
        [
            "rfc-1321.txt",
        ],
        hashes.MD5(),
    )
p">#include <sys/types.h> #include <time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include "allocate.h" #include "hash_table.h" #include "sys_net.h" #include "sys_string.h" #include "connection.h" #include "marshal.h" #include "timer.h" #undef offsetof #include "vnetd.h" #include "vcache.h" #define MODULE_NAME "VARP" #define DEBUG 1 #undef DEBUG #include "debug.h" static VarpCache *vcache = NULL; void IPMessageQueue_init(IPMessageQueue *queue, int maxlen){ queue->msg = NULL; queue->len = 0; queue->maxlen = maxlen; } void IPMessageQueue_clear(IPMessageQueue *queue){ queue->msg = NULL; queue->len = 0; } void IPMessageQueue_truncate(IPMessageQueue *queue, int n){ IPMessage **p = &queue->msg; int i; for(i = 1; *p; p = &(*p)->next, i++){ if(i == n){ *p = NULL; break; } } } void IPMessageQueue_add(IPMessageQueue *queue, IPMessage *msg){ msg->next = queue->msg; queue->msg = msg; queue->len++; if(queue->len >= queue->maxlen){ IPMessageQueue_truncate(queue, queue->maxlen); } } IPMessage * IPMessageQueue_pop(IPMessageQueue *queue){ IPMessage *msg = NULL; if(queue->len > 0){ queue->len--; msg = queue->msg; queue->msg = msg->next; msg->next = NULL; } return msg; } void VarpCache_sweep(VarpCache *z, int all); /** Send a varp protocol message. * * @param opcode varp opcode (host order) * @param vnet vnet id (in network order) * @param vmac vmac (in network order) * @return 0 on success, error code otherwise */ int varp_send(Conn *conn, uint16_t opcode, uint32_t vnet, Vmac *vmac, uint32_t addr){ int err = 0; int varp_n = sizeof(VarpHdr); VarpHdr varph = {}; varph.vnetmsghdr.id = htons(VARP_ID); varph.vnetmsghdr.opcode = htons(opcode); varph.vnet = vnet; varph.vmac = *vmac; varph.addr = addr; if(0){ struct sockaddr_in self; socklen_t self_n; getsockname(conn->sock, (struct sockaddr *)&self, &self_n); dprintf("> sockname addr=%s port=%d\n", inet_ntoa(self.sin_addr), ntohs(self.sin_port)); } dprintf("> addr=%s opcode=%d\n", inet_ntoa(conn->addr.sin_addr), opcode); dprintf("> vnet=%d vmac=" MACFMT " addr=" IPFMT "\n", ntohl(vnet), MAC6TUPLE(vmac->mac), NIPQUAD(addr)); err = marshal_bytes(conn->out, &varph, varp_n); marshal_flush(conn->out); dprintf("< err=%d\n", err); return err; } /* Test some flags. * * @param z varp entry * @param flags to test * @return nonzero if flags set */ int VCEntry_get_flags(VCEntry *z, int flags){ return z->flags & flags; } /** Set some flags. * * @param z varp entry * @param flags to set * @param set set flags on if nonzero, off if zero * @return new flags value */ int VCEntry_set_flags(VCEntry *z, int flags, int set){ if(set){ z->flags |= flags; } else { z->flags &= ~flags; } return z->flags; } /** Print a varp entry. * * @param ventry varp entry */ void VCEntry_print(VCEntry *ventry){ if(ventry){ char *c, *d; switch(ventry->state){ case VCACHE_STATE_INCOMPLETE: c = "INC"; break; case VCACHE_STATE_REACHABLE: c = "RCH"; break; case VCACHE_STATE_FAILED: c = "FLD"; break; default: c = "UNK"; break; } d = (VCEntry_get_flags(ventry, VCACHE_FLAG_PROBING) ? "P" : " "); printf("VENTRY(%p %s %s vnet=%d vmac=" MACFMT " addr=" IPFMT " time=%g)\n", ventry, c, d, ntohl(ventry->key.vnet), MAC6TUPLE(ventry->key.vmac.mac), NIPQUAD(ventry->addr), ventry->timestamp); } else { printf("VENTRY: Null!\n"); } } int VCEntry_schedule(VCEntry *ventry); void VCEntry_solicit(VCEntry *ventry); /** Function called when a varp entry timer goes off. * If the entry is still incomplete, carries on probing. * Otherwise stops probing. * * @param arg ventry */ static void ventry_timer_fn(Timer *timer){ VCEntry *ventry = timer->data; int probing = 0, scheduled = 0; //dprintf(">\n"); VCEntry_print(ventry); if(ventry->state == VCACHE_STATE_REACHABLE){ // Do nothing. } else { // Probe if haven't run out of tries, otherwise fail. if(ventry->probes < VCACHE_PROBE_MAX){ //probing = 1; ventry->probes++; scheduled = VCEntry_schedule(ventry); //VCEntry_solicit(ventry); probing = scheduled; } else { ventry->state = VCACHE_STATE_FAILED; IPMessageQueue_clear(&ventry->queue); } } if(!probing){ VCEntry_set_flags(ventry, (VCACHE_FLAG_PROBING | VCACHE_FLAG_REMOTE_PROBE | VCACHE_FLAG_LOCAL_PROBE), 0); } VCEntry_set_flags(ventry, VCACHE_FLAG_PROBING, probing); //dprintf("<\n"); } /** Schedule the varp entry timer. * * @param ventry varp entry */ int VCEntry_schedule(VCEntry *ventry){ int scheduled = 0; if(ventry->probes == 1){ scheduled = 1; Timer_set(VCACHE_LOCAL_DELAY, ventry_timer_fn, ventry); } else { VCEntry_solicit(ventry); } return scheduled; } /** Create a varp entry. Initializes the internal state. * * @param vnet vnet id * @param vmac virtual MAC address (copied) * @return ventry or null */ VCEntry * VCEntry_new(uint32_t vnet, Vmac *vmac){ VCEntry *z = ALLOCATE(VCEntry); z->state = VCACHE_STATE_INCOMPLETE; z->timestamp = time_now(); z->key.vnet = vnet; z->key.vmac = *vmac; return z; } /** Hash function for keys in the varp cache. * Hashes the vnet id and mac. * * @param k key (VCKey) * @return hashcode */ Hashcode vcache_key_hash_fn(void *k){ VCKey *key = k; Hashcode h; h = hash_2ul(key->vnet, (key->vmac.mac[0] << 24) | (key->vmac.mac[1] << 16) | (key->vmac.mac[2] << 8) | (key->vmac.mac[3] )); h = hash_hul(h, (key->vmac.mac[4] << 8) | (key->vmac.mac[5] )); return h; } /** Test equality for keys in the varp cache. * Compares vnet and mac. * * @param k1 key to compare (VCKey) * @param k2 key to compare (VCKey) * @return 1 if equal, 0 otherwise */ int vcache_key_equal_fn(void *k1, void *k2){ VCKey *key1 = k1; VCKey *key2 = k2; return (key1->vnet == key2->vnet) && (memcmp(key1->vmac.mac, key2->vmac.mac, ETH_ALEN) == 0); } void VarpCache_schedule(VarpCache *z); /** Function called when the varp table timer goes off. * Sweeps old varp cache entries and reschedules itself. * * @param arg varp table */ static void vcache_timer_fn(Timer *timer){ VarpCache *z = timer->data; //dprintf("> z=%p\n", z); if(z){ VarpCache_sweep(z, 0); VarpCache_schedule(z); } //dprintf("<\n"); } /** Schedule the varp table timer. * * @param z varp table */ void VarpCache_schedule(VarpCache *z){ Timer_set(VCACHE_ENTRY_TTL, vcache_timer_fn, z); } /** Print a varp table. * * @param z table */ void VarpCache_print(VarpCache *z){ HashTable_for_decl(entry); VCEntry *ventry; dprintf(">\n"); HashTable_for_each(entry, vcache->table){ ventry = entry->value; VCEntry_print(ventry); } dprintf("<\n"); } /** Print the varp cache. */ void vcache_print(void){ VarpCache_print(vcache); } /** Create a varp table. * * @return new table or null */ VarpCache * VarpCache_new(void){ VarpCache *z = NULL; z = ALLOCATE(VarpCache); z->table = HashTable_new(VCACHE_BUCKETS); z->table->key_equal_fn = vcache_key_equal_fn; z->table->key_hash_fn = vcache_key_hash_fn; VarpCache_schedule(z); return z; } /** Add a new entry to the varp table. * * @param z table * @param vnet vnet id * @param vmac virtual MAC address (copied) * @return new entry or null */ VCEntry * VarpCache_add(VarpCache *z, uint32_t vnet, Vmac *vmac){ VCEntry *ventry; HTEntry *entry; ventry = VCEntry_new(vnet, vmac); //dprintf("> "); VCEntry_print(ventry); entry = HashTable_add(z->table, ventry, ventry); return ventry; } /** Remove an entry from the varp table. * * @param z table * @param ventry entry to remove * @return removed count */ int VarpCache_remove(VarpCache *z, VCEntry *ventry){ return HashTable_remove(z->table, ventry); } /** Lookup an entry in the varp table. * * @param z table * @param vnet vnet id * @param vmac virtual MAC addres * @return entry found or null */ VCEntry * VarpCache_lookup(VarpCache *z, uint32_t vnet, Vmac *vmac){ VCKey key = { .vnet = vnet, .vmac = *vmac }; VCEntry *ventry; ventry = HashTable_get(z->table, &key); return ventry; } void VCEntry_solicit(VCEntry *ventry){ dprintf(">\n"); if(VCEntry_get_flags(ventry, VCACHE_FLAG_LOCAL_PROBE)){ dprintf("> local probe\n"); varp_send(vnetd->bcast_conn, VARP_OP_REQUEST, ventry->key.vnet, &ventry->key.vmac, ventry->addr); } if(VCEntry_get_flags(ventry, VCACHE_FLAG_REMOTE_PROBE)){ ConnList *l; dprintf("> remote probe\n"); for(l = vnetd->connections; l; l = l->next){ varp_send(l->conn, VARP_OP_REQUEST, ventry->key.vnet, &ventry->key.vmac, ventry->addr); } } dprintf("<\n"); } int VCEntry_resolve(VCEntry *ventry, IPMessage *msg, int flags){ int err = 0; dprintf("> "); //VCEntry_print(ventry); ventry->state = VCACHE_STATE_INCOMPLETE; VCEntry_set_flags(ventry, flags, 1); IPMessageQueue_add(&ventry->queue, msg); if(!VCEntry_get_flags(ventry, VCACHE_FLAG_PROBING)){ VCEntry_set_flags(ventry, VCACHE_FLAG_PROBING, 1); ventry->probes = 1; VCEntry_schedule(ventry); //VCEntry_solicit(ventry); } dprintf("< err=%d\n", err); return err; } /** Update a ventry. Sets the address and state to those given * and sets the timestamp to 'now'. * * @param ventry varp entry * @param addr care-of address * @param state state * @return 0 on success, error code otherwise */ int VCEntry_update(VCEntry *ventry, IPMessage *msg, VarpHdr *varph, int state){ int err = 0; double now = time_now(); if(VCEntry_get_flags(ventry, VCACHE_FLAG_PERMANENT)) goto exit; ventry->addr = varph->addr; ventry->timestamp = now; ventry->state = state; if(ventry->state == VCACHE_STATE_REACHABLE){ // Process the output queue. IPMessage *msg; while((msg = IPMessageQueue_pop(&ventry->queue))){ dprintf("> announce\n"); varp_send(msg->conn, VARP_OP_ANNOUNCE, ventry->key.vnet, &ventry->key.vmac, ventry->addr); } } exit: return err; } /** Update the ventry corresponding to the given varp header. * * @param z table * @param varph varp header * @param state state * @return 0 on success, -ENOENT if no entry found */ int VarpCache_update(VarpCache *z, IPMessage *msg, VarpHdr *varph, int state){ int err = 0; VCEntry *ventry; dprintf(">\n"); ventry = VarpCache_lookup(z, varph->vnet, &varph->vmac); if(ventry){ err = VCEntry_update(ventry, msg, varph, state); } else { err = -ENOENT; } dprintf("< err=%d\n", err); return err; } /** Put old varp entries into the incomplete state. * Permanent entries are not changed. * If 'all' is non-zero, all non-permanent entries * are put into the incomplete state, regardless of age. * * @param z table * @param all reset all entries if non-zero */ void VarpCache_sweep(VarpCache *z, int all){ HashTable_for_decl(entry); VCEntry *ventry; double now = time_now(); double old = now - VCACHE_ENTRY_TTL; dprintf(">\n"); HashTable_for_each(entry, vcache->table){ ventry = entry->value; if(!VCEntry_get_flags(ventry, VCACHE_FLAG_PERMANENT) && (all || (ventry->timestamp < old))){ ventry->state = VCACHE_STATE_INCOMPLETE; } } dprintf("<\n"); } /** Forward a varp message. * If local forwards it to remote vnetds. * If not local forwards it to local net. * * @param varph varp message to forward * @param local whether it's local or not */ void vcache_forward_varp(VarpHdr *varph, int local){ uint16_t opcode = ntohs(varph->vnetmsghdr.opcode); if(local){ ConnList *l; for(l = vnetd->connections; l; l = l->next){ varp_send(l->conn, opcode, varph->vnet, &varph->vmac, varph->addr); } } else { varp_send(vnetd->bcast_conn, opcode, varph->vnet, &varph->vmac, varph->addr); } } /** Handle a varp request. * * @param msg incoming message * @param varph varp message * @return 0 if ok, -ENOENT if no matching vif, or error code */ #if 1 int vcache_handle_request(IPMessage *msg, VarpHdr *varph, int local){ dprintf("> local=%d\n", local); vcache_forward_varp(varph, local); dprintf("<\n"); return 0; } #else int vcache_handle_request(IPMessage *msg, VarpHdr *varph, int local){ int err = -ENOENT; uint32_t vnet; Vmac *vmac; VCEntry *ventry = NULL; int reply = 0; dprintf(">\n"); vnet = htonl(varph->vnet); vmac = &varph->vmac; ventry = VarpCache_lookup(vcache, vnet, vmac); if(!ventry){ ventry = VarpCache_add(vcache, vnet, vmac); } if(local){ // Request coming from the local subnet (on our udp port). if(ventry->state == VCACHE_STATE_REACHABLE){ if(local){ // Have an entry, and it's non-local - reply (locally). // Potential out-of-date cache problem. // Should query remotely instead of replying. varp_send(conn, VARP_OP_ANNOUNCE, ventry); } } else { // Incomplete entry. Resolve. VCEntry_resolve(ventry, msg, VCACHE_FLAG_REMOTE_PROBE); } } else { // Non-local request (on one of our tcp connetions). if(ventry->state == VCACHE_STATE_REACHABLE){ if(local){ // Have an entry and it's local - reply (remotely). // Potential out-of-date cache problem. // Should query locally instead of replying. varp_send(msg->conn, VARP_OP_ANNOUNCE, ventry); } else { // Have a non-local entry - do nothing and assume someone else // will reply. } } else { // Incomplete entry. Resolve. VCEntry_resolve(ventry, msg, VCACHE_FLAG_LOCAL_PROBE); } } exit: dprintf("< err=%d\n", err); return err; } #endif /** Handle a varp announce message. * Update the matching ventry if we have one. * * @param msg incoming message * @param varp message * @return 0 if OK, -ENOENT if no matching entry */ int vcache_handle_announce(IPMessage *msg, VarpHdr *varph, int local){ int err = 0; vcache_forward_varp(varph, local); err = VarpCache_update(vcache, msg, varph, VCACHE_STATE_REACHABLE); return err; } /** Handle an incoming varp message. * * @param msg incoming message * @return 0 if OK, error code otherwise */ int vcache_handle_message(IPMessage *msg, int local){ int err = -EINVAL; VnetMsg *vmsg = msg->data; VarpHdr *varph = &vmsg->varp.varph; dprintf(">\n"); if(1){ dprintf("> src=%s:%d\n", inet_ntoa(msg->saddr.sin_addr), ntohs(msg->saddr.sin_port)); dprintf("> dst=%s:%d\n", inet_ntoa(msg->daddr.sin_addr), ntohs(msg->daddr.sin_port)); dprintf("> opcode=%d vnet=%u vmac=" MACFMT "\n", ntohs(varph->opcode), ntohl(varph->vnet), MAC6TUPLE(varph->vmac.mac)); } switch(ntohs(varph->vnetmsghdr.opcode)){ case VARP_OP_REQUEST: err = vcache_handle_request(msg, varph, local); break; case VARP_OP_ANNOUNCE: err = vcache_handle_announce(msg, varph, local); break; default: break; } dprintf("< err=%d\n", err); return err; } /** Initialize the varp cache. * * @return 0 on success, error code otherwise */ int vcache_init(void){ int err = 0; if(!vcache){ vcache = VarpCache_new(); } return err; }