/*******************************************************************-o-****** * test_dorandom * * One large request, one set of short requests. * * Returns: * Number of failures. * * XXX probably should split up into individual options. */ int test_dorandom(void) { int rval = SNMPERR_SUCCESS, failcount = 0, origrequest = (1024 * 2), origrequest_short = 19, nbytes = origrequest, shortcount = 7, i; char buf[LOCAL_MAXBUF]; OUTPUT("Random test -- large request:"); rval = sc_random(buf, &nbytes); FAILED(rval, "sc_random()."); if (nbytes != origrequest) { FAILED(SNMPERR_GENERR, "sc_random() returned different than requested."); } dump_chunk("scapitest", NULL, buf, nbytes); SUCCESS("Random test -- large request."); OUTPUT("Random test -- short requests:"); origrequest_short = 16; for (i = 0; i < shortcount; i++) { nbytes = origrequest_short; rval = sc_random(buf, &nbytes); FAILED(rval, "sc_random()."); if (nbytes != origrequest_short) { FAILED(SNMPERR_GENERR, "sc_random() returned different " "than requested."); } dump_chunk("scapitest", NULL, buf, nbytes); } /* endfor */ SUCCESS("Random test -- short requests."); return failcount; } /* end test_dorandom() */
/** * Returns pointer to allocaed & set buffer on success, size contains * number of random bytes filled. buf is NULL and *size set to KMT * error value upon failure. * * @param size Number of bytes to malloc() and fill with random bytes. * * @return a malloced buffer * */ u_char * malloc_random(size_t * size) { int rval = SNMPERR_SUCCESS; u_char *buf = (u_char *) calloc(1, *size); if (buf) { rval = sc_random(buf, size); if (rval < 0) { free_zero(buf, *size); buf = NULL; } else { *size = rval; } } return buf; } /* end malloc_random() */
_KEYTOOLS_NOT_AVAILABLE #endif /* internal or openssl */ /*******************************************************************-o-****** * encode_keychange * * Parameters: * *hashtype MIB OID for the hash transform type. * hashtype_len Length of the MIB OID hash transform type. * *oldkey Old key that is used to encodes the new key. * oldkey_len Length of oldkey in bytes. * *newkey New key that is encoded using the old key. * newkey_len Length of new key in bytes. * *kcstring Buffer to contain the KeyChange TC string. * *kcstring_len Length of kcstring buffer. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_GENERR All errors. * * * Uses oldkey and acquired random bytes to encode newkey into kcstring * according to the rules of the KeyChange TC described in RFC 2274, Section 5. * * Upon successful return, *kcstring_len contains the length of the * encoded string. * * ASSUMES Old and new key are always equal to each other, although * this may be less than the transform type hash output * output length (eg, using KeyChange for a DESPriv key when * the user also uses SHA1Auth). This also implies that the * hash placed in the second 1/2 of the key change string * will be truncated before the XOR'ing when the hash output is * larger than that 1/2 of the key change string. * * *kcstring_len will be returned as exactly twice that same * length though the input buffer may be larger. * * XXX FIX: Does not handle varibable length keys. * XXX FIX: Does not handle keys larger than the hash algorithm used. */ int encode_keychange( oid *hashtype, u_int hashtype_len, u_char *oldkey, size_t oldkey_len, u_char *newkey, size_t newkey_len, u_char *kcstring, size_t *kcstring_len) #if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) { int rval = SNMPERR_SUCCESS; size_t properlength; size_t nbytes = 0; u_char *tmpbuf = NULL; void *context = NULL; /* * Sanity check. */ if ( !hashtype || !oldkey || !newkey || !kcstring || !kcstring_len || (oldkey_len<=0) || (newkey_len<=0) || (*kcstring_len<=0) || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) { QUITFUN(SNMPERR_GENERR, encode_keychange_quit); } /* * Setup for the transform type. */ properlength = sc_get_properlength(hashtype, hashtype_len); if (properlength == SNMPERR_GENERR) QUITFUN(SNMPERR_GENERR, encode_keychange_quit); if ( (oldkey_len != newkey_len) || (*kcstring_len < (2*oldkey_len)) ) { QUITFUN(SNMPERR_GENERR, encode_keychange_quit); } properlength = SNMP_MIN((int)oldkey_len, properlength); /* * Use the old key and some random bytes to encode the new key * in the KeyChange TC format: * . Get random bytes (store in first half of kcstring), * . Hash (oldkey | random_bytes) (into second half of kcstring), * . XOR hash and newkey (into second half of kcstring). * * Getting the wrong number of random bytes is considered an error. */ nbytes = properlength; #if defined(SNMP_TESTING_CODE) && defined(RANDOMZEROS) memset(kcstring, 0, nbytes); DEBUGMSG(("encode_keychange", "** Using all zero bits for \"random\" delta of )" "the keychange string! **\n")); #else /* !SNMP_TESTING_CODE */ rval = sc_random(kcstring, &nbytes); QUITFUN(rval, encode_keychange_quit); if ((int)nbytes != properlength) { QUITFUN(SNMPERR_GENERR, encode_keychange_quit); } #endif /* !SNMP_TESTING_CODE */ tmpbuf = (u_char *)malloc(properlength*2); if (tmpbuf) { memcpy(tmpbuf, oldkey, properlength); memcpy(tmpbuf+properlength, kcstring, properlength); *kcstring_len -= properlength; rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2, kcstring+properlength, kcstring_len); QUITFUN(rval, encode_keychange_quit); *kcstring_len = (properlength*2); kcstring += properlength; nbytes = 0; while ((int)(nbytes++) < properlength) { *kcstring++ = *kcstring ^ *newkey++; } } encode_keychange_quit: if (rval != SNMPERR_SUCCESS) memset(kcstring, 0, *kcstring_len); SNMP_FREE(tmpbuf); SNMP_FREE(context); return rval; } /* end encode_keychange() */
static void smp_server(const void *data, uint16_t len, void *user_data) { struct test_data *test_data = user_data; struct bthost *bthost = hciemu_client_get_host(test_data->hciemu); const struct smp_data *smp = test_data->test_data; const struct smp_req_rsp *req; uint8_t opcode; const void *pdu; if (len < 1) { tester_warn("Received too small SMP PDU"); goto failed; } opcode = *((const uint8_t *) data); tester_print("Received SMP opcode 0x%02x", opcode); if (test_data->counter >= smp->req_count) { test_condition_complete(test_data); return; } req = &smp->req[test_data->counter++]; if (!req->expect) goto next; if (req->expect_len != len) { tester_warn("Unexpected SMP PDU length (%u != %u)", len, req->expect_len); goto failed; } switch (opcode) { case 0x01: /* Pairing Request */ memcpy(test_data->preq, data, sizeof(test_data->preq)); break; case 0x02: /* Pairing Response */ memcpy(test_data->prsp, data, sizeof(test_data->prsp)); break; case 0x03: /* Pairing Confirm */ memcpy(test_data->pcnf, data + 1, 16); goto next; case 0x04: /* Pairing Random */ memcpy(test_data->rrnd, data + 1, 16); if (smp->sc) { if (!sc_random(test_data)) goto failed; } else { if (!verify_random(data + 1)) goto failed; } goto next; case 0x0c: /* Public Key */ memcpy(test_data->remote_pk, data + 1, 64); ecdh_shared_secret(test_data->remote_pk, test_data->local_sk, test_data->dhkey); goto next; default: break; } if (memcmp(req->expect, data, len) != 0) { tester_warn("Unexpected SMP PDU"); goto failed; } next: while (true) { if (smp->req_count == test_data->counter) { test_condition_complete(test_data); break; } req = &smp->req[test_data->counter]; pdu = get_pdu(req->send); bthost_send_cid(bthost, test_data->handle, SMP_CID, pdu, req->send_len); if (req->expect) break; else test_data->counter++; } return; failed: tester_test_failed(); }