void cccurve25519_make_key_pair(struct ccrng_state *rng, ccec25519pubkey pk, ccec25519privkey sk) {
    ccrng_generate(rng,32,sk);
    sk[0] &= 248;
    sk[31] &= 127;
    sk[31] |= 64;
    cccurve25519(pk, sk, NULL);
}
// Use exactly
// 2 * ccn_sizeof(ccec_cp_order_bitlen(cp)) bytes of random in total.
// Half of the random for the actual generation, the other for the consistency check
// The consistency check may require more random, therefore a DRBG is set to cover
// this case.
int
ccec_generate_key_legacy(ccec_const_cp_t cp,  struct ccrng_state *rng, ccec_full_ctx_t key)
{
    int result;
    if((result = ccec_generate_key_internal_legacy(cp,  rng, key))) return result;
    {
        // Create an rng using a drbg.
        // Signature may use a non deterministic amount of random
        // while input rng may be limited (this is the case for PBKDF2).

        // Agnostic of DRBG
        struct ccrng_drbg_state rng_drbg;
        struct ccdrbg_info info;
        uint8_t drbg_init_salt[ccn_sizeof(ccec_cp_order_bitlen(cp))];
        cc_require((result = ccrng_generate(rng, sizeof(drbg_init_salt), drbg_init_salt))==0,errOut);

        // Set DRBG - NIST HMAC
        struct ccdrbg_nisthmac_custom custom = {
            .di = ccsha256_di(),
            .strictFIPS = 0,
        };
        ccdrbg_factory_nisthmac(&info, &custom);

        // Init the rng drbg
        uint8_t state[info.size];
        result = ccrng_drbg_init(&rng_drbg, &info, (struct ccdrbg_state *)state, sizeof(drbg_init_salt), drbg_init_salt);
        if(result == 0) {
            result = ccec_pairwise_consistency_check(key, (struct ccrng_state *)&rng_drbg) ? 0 : -1;
        }
        // Close the rng drbg
        ccrng_drbg_done(&rng_drbg);
    }
errOut:
    return result;
}
static void
record_layer(const char *name,
             bool dtls,
             bool isServer,
             bool read,
             tls_protocol_version version,
             uint16_t cipher,
             tls_buffer key,
             size_t blocksize,
             struct ccrng_state *rng)
{
    struct cipher_context context;
    size_t outsize;

    context.ofilter = tls_record_create(dtls, rng);
    if (context.ofilter == NULL)
        errx(1, "tls_record_create");

    context.ifilter = tls_record_create(dtls, rng);
    if (context.ifilter == NULL)
        errx(1, "tls_record_create");


    set_key(context.ofilter, isServer, version, cipher, key);
    set_key(context.ifilter, !isServer, version, cipher, key);

    context.inblock.length = blocksize;
    context.inblock.data = malloc(blocksize);

    if (ccrng_generate(rng, context.inblock.length, context.inblock.data))
        errx(1, "ccrng_generate");

    context.outblock.length = blocksize;
    context.outblock.data = malloc(blocksize);

    outsize = tls_record_encrypted_size(context.ofilter, tls_record_type_AppData, blocksize);

    context.encblock.data = malloc(outsize);
    context.encblock.length = outsize;

    outsize = tls_record_decrypted_size(context.ifilter, context.encblock.length);

    context.outblock.data = malloc(outsize);
    context.outblock.length = outsize;

    performance("enc+dec", name, TRIM_COUNTER, blocksize, enc_dec_func, &context);
    performance("enc", name, TRIM_COUNTER, blocksize, enc_func, &context);

    free(context.inblock.data);
    free(context.encblock.data);
    free(context.outblock.data);

    tls_record_destroy(context.ofilter);
    tls_record_destroy(context.ifilter);
}
Exemple #4
0
static double perf_ccrng_CommonCrypto_generate(unsigned long loops, size_t nbytes)
{
    uint8_t results[nbytes];
    CC_UNUSED int status;
    double time;

    perf_start();
    do {
        status = ccrng_generate((struct ccrng_state *)&nist_ctx, nbytes, results);
        cc_assert(status==0);
    } while (--loops != 0);
    time=perf_time();

    return time;
}
Exemple #5
0
int ccn_random_bits(cc_size nbits, cc_unit *r, struct ccrng_state *rng) {
    cc_size n = ccn_nof(nbits);
    
    int result = ccrng_generate(rng, ccn_sizeof_n(n), r);
	if (result)
	{
		return result;
	}
	cc_size lbits = nbits & (CCN_UNIT_BITS - 1);
    if (lbits) {
        cc_unit msuMask = (~CC_UNIT_C(0)) >> (CCN_UNIT_BITS - lbits);
        r[n - 1] &= msuMask;
    }
    return result;
}
int ccrsa_eme_pkcs1v15_encode(struct ccrng_state *rng,
                              size_t r_size, cc_unit *r,
                              size_t s_size, const uint8_t *s)

{
    cc_size n = ccrsa_n_from_size(r_size);
    uint8_t *out = ccrsa_block_start(r_size, r, 1);
    uint8_t *pad;
    size_t padlen;
    size_t i;
    
    for(uint8_t *p = (uint8_t *) r; p < out; p++) *p = 0;

    pad = out + 2;
    if ((r_size < 3) || ((r_size - 3) < s_size)) {
        return CCRSA_INVALID_INPUT;
    }
    padlen = r_size - s_size - 3;

    int result = ccrng_generate(rng, padlen, pad);
	if (result) {
		return result;
	}
	
    for(i=0; i<padlen; i++) { // pad can't have zero bytes
        while(pad[i] == 0)
            if((result = ccrng_generate(rng, 1, &pad[i])) != 0) return result;
    }
    out[0] = 0x00;
    out[1] = 0x02;
    out[2+padlen] = 0x00;
    CC_MEMCPY(out+3+padlen, s, s_size);
    ccn_swap(n, r);

    return 0;
}
Exemple #7
0
static void
memcmp_secure_securityTests(void) {

    // Random for messages
    struct ccrng_state *rng = global_test_rng;
    for (size_t i=0;i<CMP_SECURITY_TEST_ITERATION;i++)
    {
        size_t r;
        ccrng_generate(rng,sizeof(r),&r);
        r=r%CMP_SECURITY_TEST_MAX_LENGTH;
        ok(cmp_secure_timeconstantTests(r,rng,TEST_FIRST_BYTE), "Time constant check, first byte difference");
        ok(cmp_secure_timeconstantTests(r,rng,TEST_LAST_BYTE), "Time constant check, last byte difference");
        ok(cmp_secure_timeconstantTests(r,rng,TEST_RANDOM), "Time constant check, random");
        ok(cmp_secure_timeconstantTests(r,rng,TEST_EQUAL), "Time constant check of equal input - if it fails, it's a test issue");
    }
}
static double perf_ccansikdf(unsigned long loops, unsigned long size, const void *arg)
{
    const struct ccansikdf_perf_test *test=arg;
    unsigned long Zlen=test->Zlen;
    unsigned char Z[Zlen];
    unsigned long sharedInfoLen=0;
    unsigned char *sharedInfo=NULL;
    unsigned long outputLen=size;
    unsigned char output[outputLen];

    ccrng_generate(rng, Zlen, Z);

    perf_start();
    do {
        ccansikdf_x963(test->di, Zlen, Z, sharedInfoLen, sharedInfo, outputLen, output);
    } while (--loops != 0);
    return perf_time();
}
Exemple #9
0
static double perf_ccrng_system_oneshot(unsigned long loops, size_t nbytes)
{
    struct ccrng_system_state system_ctx;
    CC_UNUSED int status;
    uint8_t results[nbytes];
    double time;

    perf_start();
    do {
        status = ccrng_system_init(&system_ctx);
        cc_assert(status==0);
        status = ccrng_generate((struct ccrng_state *)&system_ctx, nbytes, results);
        cc_assert(status==0);
        ccrng_system_done(&system_ctx);
    } while (--loops != 0);
    time=perf_time();
    return time;
}
Exemple #10
0
static int tests_rng(const char *seed) {
    byteBuffer entropyBuffer;
    int status=-1; // Allocation error;

    if (seed==NULL || strlen(seed)<=0) {
        // If the seed is not in the argument, we generate one
        struct ccrng_system_state system_rng;
        size_t entropy_size=16; // Default size of the seed
        cc_require((entropyBuffer=mallocByteBuffer(entropy_size))!=NULL,errOut);
        cc_require((status=ccrng_system_init(&system_rng))==0, errOut);
        cc_require((status=ccrng_generate((struct ccrng_state *)&system_rng, entropyBuffer->len, entropyBuffer->bytes))==0, errOut);
        ccrng_system_done(&system_rng);
        cc_print("random seed value:",entropyBuffer->len,entropyBuffer->bytes);
    } else {
        // Otherwise, take the value from the arguments
        entropyBuffer = hexStringToBytes(seed);
        cc_print("input seed value:",entropyBuffer->len,entropyBuffer->bytes);
    }
    cc_require((status=ccrng_test_init(&test_rng, entropyBuffer->len,entropyBuffer->bytes))==0, errOut);
    return status;
errOut:
    printf("Error initializing test rng: %d\n",status);
    return -1;
}
Exemple #11
0
static int
cmp_secure_timeconstantTests(size_t length, struct ccrng_state *rng, uint32_t test_id) {

    // Random for messages
    uint8_t array1[length];
    uint8_t array2[length];
    int failure_cnt=0;
    int early_abort=1;
    uint32_t j,sample_counter;
    bool retry=true;

    j=0;
    while(retry)
    {
        sample_counter=0; // Index of current sample
        measurement_t timing_sample[2*CC_TIMING_SAMPLES];

        for (size_t i=0;i<2*CC_TIMING_SAMPLES+(CC_WARMUP/CC_TIMING_REPEAT);i++)
        {
            ccrng_generate(rng,length,array1);
            volatile int cmp_result;
            if ((i&1) == 0)
            {
                // -------------------------
                //      Random
                // -------------------------
                switch(test_id) {
                    // All equal, except last byte
                    case TEST_LAST_BYTE:
                        memcpy(array2,array1,length);
                        array2[length-1]^=1;
                        break;
                    // All equal, except first byte
                    case TEST_FIRST_BYTE:
                        memcpy(array2,array1,length);
                        array2[0]^=1;
                        break;
                    // Random
                    case TEST_RANDOM:
                        ccrng_generate(rng,length,array2);
                        break;
                    // All equal
                    case TEST_EQUAL:
                        memcpy(array2,array1,length);
                        break;
                    default:
                        return 0; // failure
                }

            }
            else
            {
                // -------------------------
                //      Equal
                // -------------------------
                memcpy(array2,array1,length);
            }
#if 1
            // Actual function to test
            TIMING_WITH_QUANTILE(timing_sample[sample_counter].timing,
                                 CC_TIMING_REPEAT,
                                 CC_TIMING_PERCENTILE,
                                 cmp_result=cc_cmp_safe(length, array1, array2),errOut);
#else
            // Reference which can be expected to fail
            TIMING_WITH_QUANTILE(timing_sample[sample_counter].timing,
                                 CC_TIMING_REPEAT,
                                 CC_TIMING_PERCENTILE,
                                 cmp_result=memcmp(array1, array2,length),errOut);
#endif
            timing_sample[sample_counter].group=sample_counter&1;
#if CC_WARMUP
            if (i>=CC_WARMUP/CC_TIMING_REPEAT)
#endif
            {
                sample_counter++;
            }
        }
#if CCN_OSX
        if (verbose>1) {
            char file_name[64];
            snprintf(file_name,sizeof(file_name),"corecrypto_test_cc_cmp_timings_%.2zu.csv",length);
            export_measurement_to_file(file_name,timing_sample,sample_counter);
        }
#endif
        // Process results
#if T_TEST
        // T test
        int status=T_test_isRejected(timing_sample,sample_counter);
#else
        // Wilcoxon Rank-Sum Test
        int status=WilcoxonRankSumTest(timing_sample,sample_counter);
#endif
        if (status!=0)
        {
            j++; // retry counter
            if (j>=CC_TIMING_RETRIES)
            {
                diag("Constant timing FAILED for len %d after %d attempts",length,j);
                //ok_or_fail((status==0),"Decrypt+padding constant timing");
                failure_cnt++;
                break;
            }
        }
        else
        {
            if ((verbose>1) && (j>0)) diag("Constant timing ok for len %d after %d attempts (of %d)",length,j+1,CC_TIMING_RETRIES);
            break;
        }
    } // retry

    early_abort=0;
errOut:
    if (failure_cnt || early_abort)
    {
        return 0;
    }
    return 1;
}
static OSStatus SecRSAPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding,
    const uint8_t *plainText, size_t plainTextLen,
	uint8_t *cipherText, size_t *cipherTextLen) {
    OSStatus result = errSecParam;
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    cc_unit s[ccrsa_ctx_n(pubkey)];
    const size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));

    require(cipherTextLen, errOut);
    require(*cipherTextLen >= m_size, errOut);

    uint8_t* sBytes = (uint8_t*) s;

    switch (padding) {
        case kSecPaddingNone:
            require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey), s, plainTextLen, plainText), errOut);
            require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey), s, ccrsa_ctx_m(pubkey)) < 0, errOut);
            break;

        case kSecPaddingPKCS1:
        {
            // Create PKCS1 padding:
            //
            // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
            //
            const int kMinimumPadding = 1 + 1 + 8 + 1;

            require_quiet(plainTextLen < m_size - kMinimumPadding, errOut);

            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
            
            while (prefix_zeros--)
                 *sBytes++ = 0x00;

           size_t pad_size = m_size - plainTextLen;

            *sBytes++ = 0x00;
            *sBytes++ = RSA_PKCS1_PAD_ENCRYPT;

            ccrng_generate(ccrng_seckey, pad_size - 3, sBytes);
            // Remove zeroes from the random pad

            const uint8_t* sEndOfPad = sBytes + (pad_size - 3);
            while (sBytes < sEndOfPad)
            {
                if (*sBytes == 0x00)
                    *sBytes = 0xFF; // Michael said 0xFF was good enough.

                ++sBytes;
            }

            *sBytes++ = 0x00;

            memcpy(sBytes, plainText, plainTextLen);

            ccn_swap(ccrsa_ctx_n(pubkey), s);
            break;
        }
        case kSecPaddingOAEP:
        {
            const struct ccdigest_info* di = ccsha1_di();

            const size_t encodingOverhead = 2 + 2 * di->output_size;

            require_action(m_size > encodingOverhead, errOut, result = errSecParam);
            require_action_quiet(plainTextLen < m_size - encodingOverhead, errOut, result = errSSLCrypto);

            require_noerr_action(ccrsa_oaep_encode(di,
                                                   ccrng_seckey,
                                                   m_size, s,
                                                   plainTextLen, plainText), errOut, result = errSecInternal);
           break;
        }
        default:
            goto errOut;
    }


    ccrsa_pub_crypt(pubkey, s, s);

    ccn_write_uint_padded(ccrsa_ctx_n(pubkey), s, m_size, cipherText);
    *cipherTextLen = m_size;

    result = errSecSuccess;

errOut:
    ccn_zero(ccrsa_ctx_n(pubkey), s);
    return result;
}
/* Encrypt 1 record, input.length MUST be less than the maximum record size allowed by TLS */
static int
tls_record_encrypt_1(tls_record_t ctx,
                            const tls_buffer input,
                            uint8_t contentType,
                            tls_buffer *output)
{
    int err;
    int             padding = 0, i;
    tls_buffer       payload;
    uint8_t         *charPtr;
    uint16_t        payloadSize,blockSize = 0;

    check(input.length <= TLS_MAX_FRAGMENT_SIZE);
    check(input.length > 0);

    payloadSize = tls_record_encrypted_size_1(ctx, input.length);

    check(output->length>=payloadSize);

    if(output->length<payloadSize)
    {
        check(0);
        return errSSLRecordParam; // output buffer too small
    }

    //adjust length.
    output->length=payloadSize;

    // cipher parameters:
    CipherType cipherType = ctx->writeCipher.symCipher->params->cipherType;
    const Cipher *cipher = &ctx->writeCipher.symCipher->c.cipher;
    const AEADCipher *aead = &ctx->writeCipher.symCipher->c.aead;
    blockSize = ctx->writeCipher.symCipher->params->blockSize;

    if (ctx->isDTLS)
        payloadSize-=DTLS_RECORD_HEADER_SIZE;
    else
        payloadSize-=TLS_RECORD_HEADER_SIZE;

    charPtr=output->data;
    *charPtr++=contentType;
    // We ignore the input protocol version, always use the current one
    charPtr=SSLEncodeInt(charPtr, ctx->negProtocolVersion, 2);
    if(ctx->isDTLS)
        charPtr=SSLEncodeUInt64(charPtr, ctx->writeCipher.sequenceNum);
    charPtr=SSLEncodeInt(charPtr, payloadSize, 2);

    /* Also for DTLS */
    if((ctx->negProtocolVersion >= tls_protocol_version_TLS_1_1) &&
       (cipherType == blockCipherType))
    {
        if((err = ccrng_generate(ctx->rng, blockSize, charPtr)) != 0)
            return err;
        charPtr += blockSize;
    }
    payload.data = charPtr;
    if (cipherType == aeadCipherType) {
        /* Encode the explicit iv */
        if((err = ctx->writeCipher.symCipher->c.aead.getIV(charPtr, ctx->writeCipher.cipherCtx)) != 0)
            return err;
        charPtr += TLS_AES_GCM_EXPLICIT_IV_SIZE;

        if ((err = ctx->writeCipher.symCipher->c.aead.setIV(charPtr-TLS_AES_GCM_EXPLICIT_IV_SIZE,
                                                            ctx->writeCipher.cipherCtx)) != 0)
            goto fail;
        /* TODO: If we ever add any mode other than GCM this code might have
         to be different. */
        /*
            The additional authenticated data is defined as follows:
             additional_data = seq_num + type + version + length;
             where "+" denotes concatenation.
         */
        uint8_t aad[13];
        /* First copy the 8 byte sequence number */
        SSLEncodeUInt64(aad, ctx->writeCipher.sequenceNum);
        /* Copy the 5 byte TLS header already encoded in packet to aad */
        memcpy(aad+8, charPtr-13, TLS_RECORD_HEADER_SIZE);
        /* Update length to length of plaintext after copying TLS header over */
        aad[11]=input.length>>8;
        aad[12]=input.length&0xff;
        if ((err = ctx->writeCipher.symCipher->c.aead.update(aad, 13, ctx->writeCipher.cipherCtx)) != 0)
            goto fail;
    }

    /* Copy the contents into the output buffer */
    memcpy(charPtr, input.data, input.length);
    payload.length = input.length;

    charPtr += input.length;

    /* MAC the data */
    if (cipherType != aeadCipherType) {
        if (ctx->writeCipher.di->output_size > 0)     /* Optimize away null case */
        {
            if ((err = SSLComputeMac(contentType,
                                     &payload,
                                     0,
                                     charPtr,
                                     &ctx->writeCipher,
                                     ctx->negProtocolVersion)) != 0)
                goto fail;
        }
    }

    /* For TLS 1.1 and DTLS, we would need to specifiy the IV, but instead
     we are clever like this: since the IV is just one block in front,
     we encrypt it with the rest of the data. The actual transmitted IV
     is the result of the encryption, with whatever internal IV is used.
     This method is explained in the TLS 1.1 RFC */
    if(ctx->negProtocolVersion >= tls_protocol_version_TLS_1_1 &&
       cipherType == blockCipherType)
    {
        payload.data -= blockSize;
    }

    /* Update payload to reflect encrypted data: IV, contents, mac & padding */
    payload.length = payloadSize;

    switch (cipherType) {
        case blockCipherType:
            /* Fill in the padding bytes & padding length field with the
             * padding value; the protocol only requires the last byte,
             * but filling them all in avoids leaking data */
            padding = blockSize - ((input.length+ctx->writeCipher.di->output_size) % blockSize) - 1;
            for (i = 1; i <= padding + 1; ++i)
                payload.data[payload.length - i] = padding;
            /* DROPTRHOUGH */
        case streamCipherType:
            /* Encrypt the data */
            if ((err = cipher->encrypt(payload.data,
                                       payload.data, payload.length, ctx->writeCipher.cipherCtx)) != 0)
                goto fail;
            break;
        case aeadCipherType:
            if ((err = aead->encrypt(payload.data,
                                       payload.data, payload.length, ctx->writeCipher.cipherCtx)) != 0)
                goto fail;
            break;

        default:
            check(0);
			return errSSLRecordInternal;
    }

    /* Increment the sequence number */
    IncrementUInt64(&ctx->writeCipher.sequenceNum);

    return 0;
    
fail:
    return err;
}