예제 #1
0
static SECStatus
aes_encrypt_buf(
    const unsigned char *key, unsigned int keysize,
    const unsigned char *iv, unsigned int ivsize,
    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
    const unsigned char *input, unsigned int inputlen,
    const unsigned char *aad, unsigned int aadlen, unsigned int tagsize)
{
    SECStatus rv = SECFailure;
    SECItem key_item;
    PK11SlotInfo* slot = NULL;
    PK11SymKey *symKey = NULL;
    CK_GCM_PARAMS gcm_params;
    SECItem param;

    /* Import key into NSS. */
    key_item.type = siBuffer;
    key_item.data = (unsigned char *) key;  /* const cast */
    key_item.len = keysize;
    slot = PK11_GetInternalSlot();
    symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
			       CKA_ENCRYPT, &key_item, NULL);
    PK11_FreeSlot(slot);
    slot = NULL;
    if (!symKey) {
	fprintf(stderr, "PK11_ImportSymKey failed\n");
	goto loser;
    }

    gcm_params.pIv = (unsigned char *) iv;  /* const cast */
    gcm_params.ulIvLen = ivsize;
    gcm_params.pAAD = (unsigned char *) aad;  /* const cast */
    gcm_params.ulAADLen = aadlen;
    gcm_params.ulTagBits = tagsize * 8;

    param.type = siBuffer;
    param.data = (unsigned char *) &gcm_params;
    param.len = sizeof(gcm_params);

    if (PK11_Encrypt(symKey, CKM_AES_GCM, &param,
		     output, outputlen, maxoutputlen,
		     input, inputlen) != SECSuccess) {
	fprintf(stderr, "PK11_Encrypt failed\n");
	goto loser;
    }

    rv = SECSuccess;

loser:
    if (symKey != NULL) {
	PK11_FreeSymKey(symKey);
    }
    return rv;
}
예제 #2
0
static bool ike_alg_nss_gcm(const struct encrypt_desc *alg,
			    u_int8_t *salt, size_t salt_size,
			    u_int8_t *wire_iv, size_t wire_iv_size,
			    u_int8_t *aad, size_t aad_size,
			    u_int8_t *text_and_tag,
			    size_t text_size, size_t tag_size,
			    PK11SymKey *sym_key, bool enc)
{
	/* See pk11gcmtest.c */
	bool ok = TRUE;

	chunk_t salt_chunk = {
		.ptr = salt,
		.len = salt_size,
	};
	chunk_t wire_iv_chunk = {
		.ptr = wire_iv,
		.len = wire_iv_size,
	};
	chunk_t iv = concat_chunk_chunk("IV", salt_chunk, wire_iv_chunk);

	CK_GCM_PARAMS gcm_params;
	gcm_params.pIv = iv.ptr;
	gcm_params.ulIvLen = iv.len;
	gcm_params.pAAD = aad;
	gcm_params.ulAADLen = aad_size;
	gcm_params.ulTagBits = tag_size * 8;

	SECItem param;
	param.type = siBuffer;
	param.data = (void*)&gcm_params;
	param.len = sizeof gcm_params;

	/* Output buffer for transformed data.  */
	size_t text_and_tag_size = text_size + tag_size;
	u_int8_t *out_buf = PR_Malloc(text_and_tag_size);
	unsigned int out_len = 0;

	if (enc) {
		SECStatus rv = PK11_Encrypt(sym_key, alg->common.nss_mechanism,
					    &param, out_buf, &out_len,
					    text_and_tag_size,
					    text_and_tag, text_size);
		if (rv != SECSuccess) {
			loglog(RC_LOG_SERIOUS,
			       "do_aes_gcm: PK11_Encrypt failure (err %d)", PR_GetError());
			ok = FALSE;
		} else if (out_len != text_and_tag_size) {
			loglog(RC_LOG_SERIOUS,
			       "do_aes_gcm: PK11_Encrypt output length of %u not the expected %zd",
			       out_len, text_and_tag_size);
			ok = FALSE;
		}
	} else {
		SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_GCM, &param,
					    out_buf, &out_len, text_and_tag_size,
					    text_and_tag, text_and_tag_size);
		if (rv != SECSuccess) {
			loglog(RC_LOG_SERIOUS,
			       "do_aes_gcm: PK11_Decrypt failure (err %d)", PR_GetError());
			ok = FALSE;
		} else if (out_len != text_size) {
			loglog(RC_LOG_SERIOUS,
			       "do_aes_gcm: PK11_Decrypt output length of %u not the expected %zd",
			       out_len, text_size);
			ok = FALSE;
		}
	}

	memcpy(text_and_tag, out_buf, out_len);
	PR_Free(out_buf);
	freeanychunk(iv);

	return ok;
}
예제 #3
0
/*
 * Structure is.
 *
 * struct {
 *   opaque keyName[16];
 *   opaque iv[16];
 *   opaque ciphertext<16..2^16-1>;
 *   opaque mac[32];
 * } SelfEncrypted;
 *
 * We are using AES-CBC + HMAC-SHA256 in Encrypt-then-MAC mode for
 * two reasons:
 *
 * 1. It's what we already used for tickets.
 * 2. We don't have to worry about nonce collisions as much
 *    (the chance is lower because we have a random 128-bit nonce
 *    and they are less serious than with AES-GCM).
 */
SECStatus
ssl_SelfEncryptProtectInt(
    PK11SymKey *encKey, PK11SymKey *macKey,
    const unsigned char *keyName,
    const PRUint8 *in, unsigned int inLen,
    PRUint8 *out, unsigned int *outLen, unsigned int maxOutLen)
{
    unsigned int len;
    unsigned int lenOffset;
    unsigned char iv[AES_BLOCK_SIZE];
    SECItem ivItem = { siBuffer, iv, sizeof(iv) };
    /* Write directly to out. */
    sslBuffer buf = SSL_BUFFER_FIXED(out, maxOutLen);
    SECStatus rv;

    /* Generate a random IV */
    rv = PK11_GenerateRandom(iv, sizeof(iv));
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return SECFailure;
    }

    /* Add header. */
    rv = sslBuffer_Append(&buf, keyName, SELF_ENCRYPT_KEY_NAME_LEN);
    if (rv != SECSuccess) {
        return SECFailure;
    }
    rv = sslBuffer_Append(&buf, iv, sizeof(iv));
    if (rv != SECSuccess) {
        return SECFailure;
    }

    /* Leave space for the length of the ciphertext. */
    rv = sslBuffer_Skip(&buf, 2, &lenOffset);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    /* Encode the ciphertext in place. */
    rv = PK11_Encrypt(encKey, CKM_AES_CBC_PAD, &ivItem,
                      SSL_BUFFER_NEXT(&buf), &len,
                      SSL_BUFFER_SPACE(&buf), in, inLen);
    if (rv != SECSuccess) {
        return SECFailure;
    }
    rv = sslBuffer_Skip(&buf, len, NULL);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    rv = sslBuffer_InsertLength(&buf, lenOffset, 2);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    /* MAC the entire output buffer into the output. */
    PORT_Assert(buf.space - buf.len >= SHA256_LENGTH);
    rv = ssl_MacBuffer(macKey, CKM_SHA256_HMAC,
                       SSL_BUFFER_BASE(&buf), /* input */
                       SSL_BUFFER_LEN(&buf),
                       SSL_BUFFER_NEXT(&buf), &len, /* output */
                       SHA256_LENGTH);
    if (rv != SECSuccess) {
        return SECFailure;
    }
    rv = sslBuffer_Skip(&buf, len, NULL);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    *outLen = SSL_BUFFER_LEN(&buf);
    return SECSuccess;
}