tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sftkike.c (48907B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * This file implements PKCS 11 on top of our existing security modules
      6 *
      7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
      8 *   This implementation has two slots:
      9 *      slot 1 is our generic crypto support. It does not require login.
     10 *   It supports Public Key ops, and all they bulk ciphers and hashes.
     11 *   It can also support Private Key ops for imported Private keys. It does
     12 *   not have any token storage.
     13 *      slot 2 is our private key support. It requires a login before use. It
     14 *   can store Private Keys and Certs as token objects. Currently only private
     15 *   keys and their associated Certificates are saved on the token.
     16 *
     17 *   In this implementation, session objects are only visible to the session
     18 *   that created or generated them.
     19 */
     20 #include "seccomon.h"
     21 #include "secitem.h"
     22 #include "secport.h"
     23 #include "blapi.h"
     24 #include "pkcs11.h"
     25 #include "pkcs11i.h"
     26 #include "pkcs1sig.h"
     27 #include "lowkeyi.h"
     28 #include "secder.h"
     29 #include "secdig.h"
     30 #include "lowpbe.h" /* We do PBE below */
     31 #include "pkcs11t.h"
     32 #include "secoid.h"
     33 #include "alghmac.h"
     34 #include "softoken.h"
     35 #include "secasn1.h"
     36 #include "secerr.h"
     37 
     38 #include "prprf.h"
     39 #include "prenv.h"
     40 
     41 /*
     42 * A common prfContext to handle both hmac and aes xcbc
     43 * hash contexts have non-null hashObj and hmac, aes
     44 * contexts have non-null aes */
     45 typedef struct prfContextStr {
     46    HASH_HashType hashType;
     47    const SECHashObject *hashObj;
     48    HMACContext *hmac;
     49    AESContext *aes;
     50    unsigned int nextChar;
     51    unsigned char padBuf[AES_BLOCK_SIZE];
     52    unsigned char macBuf[AES_BLOCK_SIZE];
     53    unsigned char k1[AES_BLOCK_SIZE];
     54    unsigned char k2[AES_BLOCK_SIZE];
     55    unsigned char k3[AES_BLOCK_SIZE];
     56 } prfContext;
     57 
     58 /* iv full of zeros used in several places in aes xcbc */
     59 static const unsigned char iv_zero[] = {
     60    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     61    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     62 };
     63 
     64 /*
     65 * Generate AES XCBC keys from the AES MAC key.
     66 * k1 is used in the actual mac.
     67 * k2 and k3 are used in the final pad step.
     68 */
     69 static CK_RV
     70 sftk_aes_xcbc_get_keys(const unsigned char *keyValue, unsigned int keyLen,
     71                       unsigned char *k1, unsigned char *k2, unsigned char *k3)
     72 {
     73    SECStatus rv;
     74    CK_RV crv;
     75    unsigned int tmpLen;
     76    AESContext *aes_context = NULL;
     77    unsigned char newKey[AES_BLOCK_SIZE];
     78 
     79    /* AES XCBC keys. k1, k2, and k3 are derived by encrypting
     80     * k1data, k2data, and k3data with the mac key.
     81     */
     82    static const unsigned char k1data[] = {
     83        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
     84        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
     85    };
     86    static const unsigned char k2data[] = {
     87        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
     88        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
     89    };
     90    static const unsigned char k3data[] = {
     91        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
     92        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
     93    };
     94 
     95    /* k1_0 = aes_ecb(0, k1data) */
     96    static const unsigned char k1_0[] = {
     97        0xe1, 0x4d, 0x5d, 0x0e, 0xe2, 0x77, 0x15, 0xdf,
     98        0x08, 0xb4, 0x15, 0x2b, 0xa2, 0x3d, 0xa8, 0xe0
     99 
    100    };
    101    /* k2_0 = aes_ecb(0, k2data) */
    102    static const unsigned char k2_0[] = {
    103        0x5e, 0xba, 0x73, 0xf8, 0x91, 0x42, 0xc5, 0x48,
    104        0x80, 0xf6, 0x85, 0x94, 0x37, 0x3c, 0x5c, 0x37
    105    };
    106    /* k3_0 = aes_ecb(0, k3data) */
    107    static const unsigned char k3_0[] = {
    108        0x8d, 0x34, 0xef, 0xcb, 0x3b, 0xd5, 0x45, 0xca,
    109        0x06, 0x2a, 0xec, 0xdf, 0xef, 0x7c, 0x0b, 0xfa
    110    };
    111 
    112    /* first make sure out input key is the correct length
    113     * rfc 4434. If key is shorter, pad with zeros to the
    114     * the right. If key is longer newKey = aes_xcbc(0, key, keyLen).
    115     */
    116    if (keyLen < AES_BLOCK_SIZE) {
    117        PORT_Memcpy(newKey, keyValue, keyLen);
    118        PORT_Memset(&newKey[keyLen], 0, AES_BLOCK_SIZE - keyLen);
    119        keyValue = newKey;
    120    } else if (keyLen > AES_BLOCK_SIZE) {
    121        /* calculate our new key = aes_xcbc(0, key, keyLen). Because the
    122         * key above is fixed (0), we can precalculate k1, k2, and k3.
    123         * if this code ever needs to be more generic (support any xcbc
    124         * function rather than just aes, we would probably want to just
    125         * recurse here using our prf functions. This would be safe because
    126         * the recurse case would have keyLen == blocksize and thus skip
    127         * this conditional.
    128         */
    129        aes_context = AES_CreateContext(k1_0, iv_zero, NSS_AES_CBC,
    130                                        PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
    131        /* we know the following loop will execute at least once */
    132        while (keyLen > AES_BLOCK_SIZE) {
    133            rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,
    134                             keyValue, AES_BLOCK_SIZE);
    135            if (rv != SECSuccess) {
    136                goto fail;
    137            }
    138            keyValue += AES_BLOCK_SIZE;
    139            keyLen -= AES_BLOCK_SIZE;
    140        }
    141        PORT_Memcpy(newKey, keyValue, keyLen);
    142        sftk_xcbc_mac_pad(newKey, keyLen, AES_BLOCK_SIZE, k2_0, k3_0);
    143        rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,
    144                         newKey, AES_BLOCK_SIZE);
    145        if (rv != SECSuccess) {
    146            goto fail;
    147        }
    148        keyValue = newKey;
    149        AES_DestroyContext(aes_context, PR_TRUE);
    150    }
    151    /* the length of the key in keyValue is known to be AES_BLOCK_SIZE,
    152     * either because it was on input, or it was shorter and extended, or
    153     * because it was mac'd down using aes_xcbc_prf.
    154     */
    155    aes_context = AES_CreateContext(keyValue, iv_zero,
    156                                    NSS_AES, PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
    157    if (aes_context == NULL) {
    158        goto fail;
    159    }
    160    rv = AES_Encrypt(aes_context, k1, &tmpLen, AES_BLOCK_SIZE,
    161                     k1data, sizeof(k1data));
    162    if (rv != SECSuccess) {
    163        goto fail;
    164    }
    165    rv = AES_Encrypt(aes_context, k2, &tmpLen, AES_BLOCK_SIZE,
    166                     k2data, sizeof(k2data));
    167    if (rv != SECSuccess) {
    168        goto fail;
    169    }
    170    rv = AES_Encrypt(aes_context, k3, &tmpLen, AES_BLOCK_SIZE,
    171                     k3data, sizeof(k3data));
    172    if (rv != SECSuccess) {
    173        goto fail;
    174    }
    175    AES_DestroyContext(aes_context, PR_TRUE);
    176    PORT_Memset(newKey, 0, AES_BLOCK_SIZE);
    177    return CKR_OK;
    178 fail:
    179    crv = sftk_MapCryptError(PORT_GetError());
    180    if (aes_context) {
    181        AES_DestroyContext(aes_context, PR_TRUE);
    182    }
    183    PORT_Memset(k1, 0, AES_BLOCK_SIZE);
    184    PORT_Memset(k2, 0, AES_BLOCK_SIZE);
    185    PORT_Memset(k3, 0, AES_BLOCK_SIZE);
    186    PORT_Memset(newKey, 0, AES_BLOCK_SIZE);
    187    return crv;
    188 }
    189 
    190 /* encode the final pad block of aes xcbc, padBuf is modified */
    191 CK_RV
    192 sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
    193                  unsigned int blockSize, const unsigned char *k2,
    194                  const unsigned char *k3)
    195 {
    196    unsigned int i;
    197    if (bufLen == blockSize) {
    198        for (i = 0; i < blockSize; i++) {
    199            padBuf[i] ^= k2[i];
    200        }
    201    } else {
    202        padBuf[bufLen++] = 0x80;
    203        for (i = bufLen; i < blockSize; i++) {
    204            padBuf[i] = 0x00;
    205        }
    206        for (i = 0; i < blockSize; i++) {
    207            padBuf[i] ^= k3[i];
    208        }
    209    }
    210    return CKR_OK;
    211 }
    212 
    213 /* Map the mechanism to the underlying hash. If the type is not a hash
    214 * or HMAC, return HASH_AlgNULL. This can happen legitimately if
    215 * we are doing AES XCBC */
    216 static HASH_HashType
    217 sftk_map_hmac_to_hash(CK_MECHANISM_TYPE type)
    218 {
    219    switch (type) {
    220        case CKM_SHA_1_HMAC:
    221        case CKM_SHA_1:
    222            return HASH_AlgSHA1;
    223        case CKM_MD5_HMAC:
    224        case CKM_MD5:
    225            return HASH_AlgMD5;
    226        case CKM_MD2_HMAC:
    227        case CKM_MD2:
    228            return HASH_AlgMD2;
    229        case CKM_SHA224_HMAC:
    230        case CKM_SHA224:
    231            return HASH_AlgSHA224;
    232        case CKM_SHA256_HMAC:
    233        case CKM_SHA256:
    234            return HASH_AlgSHA256;
    235        case CKM_SHA384_HMAC:
    236        case CKM_SHA384:
    237            return HASH_AlgSHA384;
    238        case CKM_SHA512_HMAC:
    239        case CKM_SHA512:
    240            return HASH_AlgSHA512;
    241    }
    242    return HASH_AlgNULL;
    243 }
    244 
    245 /*
    246 * Generally setup the context based on the mechanism.
    247 * If the mech is HMAC, context->hashObj should be set
    248 * Otherwise it is assumed to be AES XCBC. prf_setup
    249 * checks these assumptions and will return an error
    250 * if they are not met. NOTE: this function does not allocate
    251 * anything, so there is no requirement to free context after
    252 * prf_setup like there is if you call prf_init.
    253 */
    254 static CK_RV
    255 prf_setup(prfContext *context, CK_MECHANISM_TYPE mech)
    256 {
    257    context->hashType = sftk_map_hmac_to_hash(mech);
    258    context->hashObj = NULL;
    259    context->hmac = NULL;
    260    context->aes = NULL;
    261    if (context->hashType != HASH_AlgNULL) {
    262        context->hashObj = HASH_GetRawHashObject(context->hashType);
    263        if (context->hashObj == NULL) {
    264            return CKR_GENERAL_ERROR;
    265        }
    266        return CKR_OK;
    267    } else if (mech == CKM_AES_XCBC_MAC) {
    268        return CKR_OK;
    269    }
    270    return CKR_MECHANISM_PARAM_INVALID;
    271 }
    272 
    273 /* return the underlying prf length for this context. This will
    274 * function once the context is setup */
    275 static CK_RV
    276 prf_length(prfContext *context)
    277 {
    278    if (context->hashObj) {
    279        return context->hashObj->length;
    280    }
    281    return AES_BLOCK_SIZE; /* AES */
    282 }
    283 
    284 /* set up the key for the prf. prf_update or prf_final should not be called if
    285 * prf_init has not been called first. Once prf_init returns hmac and
    286 * aes contexts should set and valid.
    287 */
    288 static CK_RV
    289 prf_init(prfContext *context, const unsigned char *keyValue,
    290         unsigned int keyLen)
    291 {
    292    CK_RV crv;
    293 
    294    context->hmac = NULL;
    295    if (context->hashObj) {
    296        context->hmac = HMAC_Create(context->hashObj,
    297                                    keyValue, keyLen, PR_FALSE);
    298        if (context->hmac == NULL) {
    299            return sftk_MapCryptError(PORT_GetError());
    300        }
    301        HMAC_Begin(context->hmac);
    302    } else {
    303        crv = sftk_aes_xcbc_get_keys(keyValue, keyLen, context->k1,
    304                                     context->k2, context->k3);
    305        if (crv != CKR_OK)
    306            return crv;
    307        context->nextChar = 0;
    308        context->aes = AES_CreateContext(context->k1, iv_zero, NSS_AES_CBC,
    309                                         PR_TRUE, sizeof(context->k1), AES_BLOCK_SIZE);
    310        if (context->aes == NULL) {
    311            crv = sftk_MapCryptError(PORT_GetError());
    312            PORT_Memset(context->k1, 0, sizeof(context->k1));
    313            PORT_Memset(context->k2, 0, sizeof(context->k2));
    314            PORT_Memset(context->k3, 0, sizeof(context->k2));
    315            return crv;
    316        }
    317    }
    318    return CKR_OK;
    319 }
    320 
    321 /*
    322 * process input to the prf
    323 */
    324 static CK_RV
    325 prf_update(prfContext *context, const unsigned char *buf, unsigned int len)
    326 {
    327    unsigned int tmpLen;
    328    SECStatus rv;
    329 
    330    if (context->hmac) {
    331        HMAC_Update(context->hmac, buf, len);
    332    } else {
    333        /* AES MAC XCBC*/
    334        /* We must keep the last block back so that it can be processed in
    335         * final. This is why we only check that nextChar + len > blocksize,
    336         * rather than checking that nextChar + len >= blocksize */
    337        while (context->nextChar + len > AES_BLOCK_SIZE) {
    338            if (context->nextChar != 0) {
    339                /* first handle fill in any partial blocks in the buffer */
    340                unsigned int left = AES_BLOCK_SIZE - context->nextChar;
    341                /* note: left can be zero */
    342                PORT_Memcpy(context->padBuf + context->nextChar, buf, left);
    343                /* NOTE: AES MAC XCBC xors the data with the previous block
    344                 * We don't do that step here because our AES_Encrypt mode
    345                 * is CBC, which does the xor automatically */
    346                rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
    347                                 sizeof(context->macBuf), context->padBuf,
    348                                 sizeof(context->padBuf));
    349                if (rv != SECSuccess) {
    350                    return sftk_MapCryptError(PORT_GetError());
    351                }
    352                context->nextChar = 0;
    353                len -= left;
    354                buf += left;
    355            } else {
    356                /* optimization. if we have complete blocks to write out
    357                 * (and will still have leftover blocks for padbuf in the end).
    358                 * we can mac directly out of our buffer without first copying
    359                 * them to padBuf */
    360                rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
    361                                 sizeof(context->macBuf), buf, AES_BLOCK_SIZE);
    362                if (rv != SECSuccess) {
    363                    return sftk_MapCryptError(PORT_GetError());
    364                }
    365                len -= AES_BLOCK_SIZE;
    366                buf += AES_BLOCK_SIZE;
    367            }
    368        }
    369        PORT_Memcpy(context->padBuf + context->nextChar, buf, len);
    370        context->nextChar += len;
    371    }
    372    return CKR_OK;
    373 }
    374 
    375 /*
    376 * free the data associated with the prf. Clear any possible CSPs
    377 * This can safely be called on any context after prf_setup. It can
    378 * also be called an an already freed context.
    379 * A free context can be reused by calling prf_init again without
    380 * the need to call prf_setup.
    381 */
    382 static void
    383 prf_free(prfContext *context)
    384 {
    385    if (context->hmac) {
    386        HMAC_Destroy(context->hmac, PR_TRUE);
    387        context->hmac = NULL;
    388    }
    389    if (context->aes) {
    390        PORT_Memset(context->k1, 0, sizeof(context->k1));
    391        PORT_Memset(context->k2, 0, sizeof(context->k2));
    392        PORT_Memset(context->k3, 0, sizeof(context->k2));
    393        PORT_Memset(context->padBuf, 0, sizeof(context->padBuf));
    394        PORT_Memset(context->macBuf, 0, sizeof(context->macBuf));
    395        AES_DestroyContext(context->aes, PR_TRUE);
    396        context->aes = NULL;
    397    }
    398 }
    399 
    400 /*
    401 * extract the final prf value. On success, this has the side effect of
    402 * also freeing the context data and clearing the keys
    403 */
    404 static CK_RV
    405 prf_final(prfContext *context, unsigned char *buf, unsigned int len)
    406 {
    407    unsigned int tmpLen;
    408    SECStatus rv;
    409 
    410    if (context->hmac) {
    411        unsigned int outLen;
    412        HMAC_Finish(context->hmac, buf, &outLen, len);
    413        if (outLen != len) {
    414            return CKR_GENERAL_ERROR;
    415        }
    416    } else {
    417        /* prf_update had guarrenteed that the last full block is still in
    418         * the padBuf if the input data is a multiple of the blocksize. This
    419         * allows sftk_xcbc_mac_pad to process that pad buf accordingly */
    420        CK_RV crv = sftk_xcbc_mac_pad(context->padBuf, context->nextChar,
    421                                      AES_BLOCK_SIZE, context->k2, context->k3);
    422        if (crv != CKR_OK) {
    423            return crv;
    424        }
    425        rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
    426                         sizeof(context->macBuf), context->padBuf, AES_BLOCK_SIZE);
    427        if (rv != SECSuccess) {
    428            return sftk_MapCryptError(PORT_GetError());
    429        }
    430        PORT_Memcpy(buf, context->macBuf, len);
    431    }
    432    prf_free(context);
    433    return CKR_OK;
    434 }
    435 
    436 /*
    437 * There are four flavors of ike prf functions here.
    438 * ike_prf is used in both ikeV1 and ikeV2 to generate
    439 * an initial key that all the other keys are generated with.
    440 *
    441 * These functions are called from NSC_DeriveKey with the inKey value
    442 * already looked up, and it expects the CKA_VALUE for outKey to be set.
    443 *
    444 * Depending on usage it returns either:
    445 *    1. prf(Ni|Nr, inKey); (bDataAsKey=TRUE, bRekey=FALSE)
    446 *    2. prf(inKey, Ni|Nr); (bDataAsKkey=FALSE, bRekey=FALSE)
    447 *    3. prf(inKey, newKey | Ni | Nr); (bDataAsKey=FALSE, bRekey=TRUE)
    448 * The resulting output key is always the length of the underlying prf
    449 * (as returned by prf_length()).
    450 * The combination of bDataAsKey=TRUE and bRekey=TRUE is not allowed
    451 *
    452 * Case 1 is used in
    453 *    a. ikev2 (rfc5996) inKey is called g^ir, the output is called SKEYSEED
    454 *    b. ikev1 (rfc2409) inKey is called g^ir, the output is called SKEYID
    455 * Case 2 is used in ikev1 (rfc2409) inkey is called pre-shared-key, output
    456 *    is called SKEYID
    457 * Case 3 is used in ikev2 (rfc5996) rekey case, inKey is SK_d, newKey is
    458 *    g^ir (new), the output is called SKEYSEED
    459 */
    460 CK_RV
    461 sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
    462             const CK_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey)
    463 {
    464    SFTKAttribute *newKeyValue = NULL;
    465    SFTKObject *newKeyObj = NULL;
    466    unsigned char outKeyData[HASH_LENGTH_MAX];
    467    unsigned char *newInKey = NULL;
    468    unsigned int newInKeySize = 0;
    469    unsigned int macSize;
    470    CK_RV crv = CKR_OK;
    471    prfContext context;
    472 
    473    crv = prf_setup(&context, params->prfMechanism);
    474    if (crv != CKR_OK) {
    475        return crv;
    476    }
    477    macSize = prf_length(&context);
    478    if ((params->bDataAsKey) && (params->bRekey)) {
    479        return CKR_ARGUMENTS_BAD;
    480    }
    481    if (params->bRekey) {
    482        /* lookup the value of new key from the session and key handle */
    483        SFTKSession *session = sftk_SessionFromHandle(hSession);
    484        if (session == NULL) {
    485            return CKR_SESSION_HANDLE_INVALID;
    486        }
    487        newKeyObj = sftk_ObjectFromHandle(params->hNewKey, session);
    488        sftk_FreeSession(session);
    489        if (newKeyObj == NULL) {
    490            return CKR_KEY_HANDLE_INVALID;
    491        }
    492        newKeyValue = sftk_FindAttribute(newKeyObj, CKA_VALUE);
    493        if (newKeyValue == NULL) {
    494            crv = CKR_KEY_HANDLE_INVALID;
    495            goto fail;
    496        }
    497    }
    498    if (params->bDataAsKey) {
    499        /* The key is Ni || Np, so we need to concatenate them together first */
    500        newInKeySize = params->ulNiLen + params->ulNrLen;
    501        newInKey = PORT_Alloc(newInKeySize);
    502        if (newInKey == NULL) {
    503            crv = CKR_HOST_MEMORY;
    504            goto fail;
    505        }
    506        PORT_Memcpy(newInKey, params->pNi, params->ulNiLen);
    507        PORT_Memcpy(newInKey + params->ulNiLen, params->pNr, params->ulNrLen);
    508        crv = prf_init(&context, newInKey, newInKeySize);
    509        if (crv != CKR_OK) {
    510            goto fail;
    511        }
    512        /* key as the data */
    513        crv = prf_update(&context, inKey->attrib.pValue,
    514                         inKey->attrib.ulValueLen);
    515        if (crv != CKR_OK) {
    516            goto fail;
    517        }
    518    } else {
    519        crv = prf_init(&context, inKey->attrib.pValue,
    520                       inKey->attrib.ulValueLen);
    521        if (crv != CKR_OK) {
    522            goto fail;
    523        }
    524        if (newKeyValue) {
    525            crv = prf_update(&context, newKeyValue->attrib.pValue,
    526                             newKeyValue->attrib.ulValueLen);
    527            if (crv != CKR_OK) {
    528                goto fail;
    529            }
    530        }
    531        crv = prf_update(&context, params->pNi, params->ulNiLen);
    532        if (crv != CKR_OK) {
    533            goto fail;
    534        }
    535        crv = prf_update(&context, params->pNr, params->ulNrLen);
    536        if (crv != CKR_OK) {
    537            goto fail;
    538        }
    539    }
    540    crv = prf_final(&context, outKeyData, macSize);
    541    if (crv != CKR_OK) {
    542        goto fail;
    543    }
    544 
    545    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, macSize);
    546 fail:
    547    if (newInKey) {
    548        PORT_ZFree(newInKey, newInKeySize);
    549    }
    550    if (newKeyValue) {
    551        sftk_FreeAttribute(newKeyValue);
    552    }
    553    if (newKeyObj) {
    554        sftk_FreeObject(newKeyObj);
    555    }
    556    PORT_Memset(outKeyData, 0, macSize);
    557    prf_free(&context);
    558    return crv;
    559 }
    560 
    561 /*
    562 * The second flavor of  ike prf is ike1_prf.
    563 *
    564 * It is used by ikeV1 to generate the various session keys used in the
    565 * connection. It uses the initial key, an optional previous key, and a one byte
    566 * key number to generate a unique key for each of the various session
    567 * functions (encryption, decryption, mac). These keys expect a key size
    568 * (as they may vary in length based on usage). If no length is provided,
    569 * it will default to the length of the prf.
    570 *
    571 * This function returns either:
    572 *     prf(inKey, gxyKey || CKYi || CKYr || key_number)
    573 * or
    574 *     prf(inKey, prevkey || gxyKey || CKYi || CKYr || key_number)
    575 * depending on the stats of bHasPrevKey
    576 *
    577 * This is defined in rfc2409. For each of the following keys.
    578 *     inKey is  SKEYID,    gxyKey is g^xy
    579 *     for outKey = SKEYID_d, bHasPrevKey = false, key_number = 0
    580 *     for outKey = SKEYID_a, prevKey= SKEYID_d,   key_number = 1
    581 *     for outKey = SKEYID_e, prevKey= SKEYID_a,   key_number = 2
    582 */
    583 CK_RV
    584 sftk_ike1_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
    585              const CK_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,
    586              unsigned int keySize)
    587 {
    588    SFTKAttribute *gxyKeyValue = NULL;
    589    SFTKObject *gxyKeyObj = NULL;
    590    SFTKAttribute *prevKeyValue = NULL;
    591    SFTKObject *prevKeyObj = NULL;
    592    SFTKSession *session;
    593    unsigned char outKeyData[HASH_LENGTH_MAX];
    594    unsigned int macSize;
    595    CK_RV crv;
    596    prfContext context;
    597 
    598    crv = prf_setup(&context, params->prfMechanism);
    599    if (crv != CKR_OK) {
    600        return crv;
    601    }
    602    macSize = prf_length(&context);
    603    if (keySize > macSize) {
    604        return CKR_KEY_SIZE_RANGE;
    605    }
    606    if (keySize == 0) {
    607        keySize = macSize;
    608    }
    609 
    610    /* lookup the two keys from their passed in handles */
    611    session = sftk_SessionFromHandle(hSession);
    612    if (session == NULL) {
    613        return CKR_SESSION_HANDLE_INVALID;
    614    }
    615    gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
    616    if (params->bHasPrevKey) {
    617        prevKeyObj = sftk_ObjectFromHandle(params->hPrevKey, session);
    618    }
    619    sftk_FreeSession(session);
    620    if ((gxyKeyObj == NULL) || ((params->bHasPrevKey) &&
    621                                (prevKeyObj == NULL))) {
    622        crv = CKR_KEY_HANDLE_INVALID;
    623        goto fail;
    624    }
    625    gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);
    626    if (gxyKeyValue == NULL) {
    627        crv = CKR_KEY_HANDLE_INVALID;
    628        goto fail;
    629    }
    630    if (prevKeyObj) {
    631        prevKeyValue = sftk_FindAttribute(prevKeyObj, CKA_VALUE);
    632        if (prevKeyValue == NULL) {
    633            crv = CKR_KEY_HANDLE_INVALID;
    634            goto fail;
    635        }
    636    }
    637 
    638    /* outKey = prf(inKey, [prevKey|] gxyKey | CKYi | CKYr | keyNumber) */
    639    crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
    640    if (crv != CKR_OK) {
    641        goto fail;
    642    }
    643    if (prevKeyValue) {
    644        crv = prf_update(&context, prevKeyValue->attrib.pValue,
    645                         prevKeyValue->attrib.ulValueLen);
    646        if (crv != CKR_OK) {
    647            goto fail;
    648        }
    649    }
    650    crv = prf_update(&context, gxyKeyValue->attrib.pValue,
    651                     gxyKeyValue->attrib.ulValueLen);
    652    if (crv != CKR_OK) {
    653        goto fail;
    654    }
    655    crv = prf_update(&context, params->pCKYi, params->ulCKYiLen);
    656    if (crv != CKR_OK) {
    657        goto fail;
    658    }
    659    crv = prf_update(&context, params->pCKYr, params->ulCKYrLen);
    660    if (crv != CKR_OK) {
    661        goto fail;
    662    }
    663    crv = prf_update(&context, &params->keyNumber, 1);
    664    if (crv != CKR_OK) {
    665        goto fail;
    666    }
    667    crv = prf_final(&context, outKeyData, macSize);
    668    if (crv != CKR_OK) {
    669        goto fail;
    670    }
    671 
    672    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
    673 fail:
    674    if (gxyKeyValue) {
    675        sftk_FreeAttribute(gxyKeyValue);
    676    }
    677    if (prevKeyValue) {
    678        sftk_FreeAttribute(prevKeyValue);
    679    }
    680    if (gxyKeyObj) {
    681        sftk_FreeObject(gxyKeyObj);
    682    }
    683    if (prevKeyObj) {
    684        sftk_FreeObject(prevKeyObj);
    685    }
    686    PORT_Memset(outKeyData, 0, macSize);
    687    prf_free(&context);
    688    return crv;
    689 }
    690 
    691 /*
    692 * The third flavor of ike prf is ike1_appendix_b.
    693 *
    694 * It is used by ikeV1 to generate longer key material from skeyid_e.
    695 * Unlike ike1_prf, if no length is provided, this function
    696 * will generate a KEY_RANGE_ERROR.
    697 *
    698 * This function returns (from rfc2409 appendix b):
    699 * Ka = K1 | K2 | K3 | K4 |... Kn
    700 * where:
    701 *       K1 = prf(K, [gxyKey]|[extraData]) or prf(K, 0) if gxyKey and extraData
    702 *                                                      ar not present.
    703 *       K2 = prf(K, K1|[gxyKey]|[extraData])
    704 *       K3 = prf(K, K2|[gxyKey]|[extraData])
    705 *       K4 = prf(K, K3|[gxyKey]|[extraData])
    706 *            .
    707 *       Kn = prf(K, K(n-1)|[gxyKey]|[extraData])
    708 * K = inKey
    709 */
    710 CK_RV
    711 sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
    712                         const CK_IKE1_EXTENDED_DERIVE_PARAMS *params,
    713                         SFTKObject *outKey, unsigned int keySize)
    714 {
    715    SFTKAttribute *gxyKeyValue = NULL;
    716    SFTKObject *gxyKeyObj = NULL;
    717    unsigned char *outKeyData = NULL;
    718    unsigned char *thisKey = NULL;
    719    unsigned char *lastKey = NULL;
    720    unsigned int macSize;
    721    unsigned int outKeySize;
    722    unsigned int genKeySize;
    723    PRBool quickMode = PR_FALSE;
    724    CK_RV crv;
    725    prfContext context;
    726 
    727    if ((params->ulExtraDataLen != 0) && (params->pExtraData == NULL)) {
    728        return CKR_ARGUMENTS_BAD;
    729    }
    730    crv = prf_setup(&context, params->prfMechanism);
    731    if (crv != CKR_OK) {
    732        return crv;
    733    }
    734 
    735    if (params->bHasKeygxy) {
    736        SFTKSession *session;
    737        session = sftk_SessionFromHandle(hSession);
    738        if (session == NULL) {
    739            return CKR_SESSION_HANDLE_INVALID;
    740        }
    741        gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
    742        sftk_FreeSession(session);
    743        if (gxyKeyObj == NULL) {
    744            crv = CKR_KEY_HANDLE_INVALID;
    745            goto fail;
    746        }
    747        gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);
    748        if (gxyKeyValue == NULL) {
    749            crv = CKR_KEY_HANDLE_INVALID;
    750            goto fail;
    751        }
    752        quickMode = PR_TRUE;
    753    }
    754 
    755    if (params->ulExtraDataLen != 0) {
    756        quickMode = PR_TRUE;
    757    }
    758 
    759    macSize = prf_length(&context);
    760 
    761    if (keySize == 0) {
    762        keySize = macSize;
    763    }
    764 
    765    /* In appendix B, we are just expanding or contracting a single key.
    766     * If the input key is less than or equal to the the key size we want,
    767     * just subset the original key. In quick mode we are actually getting
    768     * new keys (salted with our seed data and our gxy key), so we want to
    769     * run through our algorithm */
    770    if ((!quickMode) && (keySize <= inKey->attrib.ulValueLen)) {
    771        return sftk_forceAttribute(outKey, CKA_VALUE,
    772                                   inKey->attrib.pValue, keySize);
    773    }
    774 
    775    outKeySize = PR_ROUNDUP(keySize, macSize);
    776    outKeyData = PORT_Alloc(outKeySize);
    777    if (outKeyData == NULL) {
    778        crv = CKR_HOST_MEMORY;
    779        goto fail;
    780    }
    781 
    782    /*
    783     * this loop generates on block of the prf, basically
    784     *   kn = prf(key, Kn-1 | [Keygxy] | [ExtraData])
    785     *   Kn is thisKey, Kn-1 is lastKey
    786     *   key is inKey
    787     */
    788    thisKey = outKeyData;
    789    for (genKeySize = 0; genKeySize < keySize; genKeySize += macSize) {
    790        PRBool hashedData = PR_FALSE;
    791        crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
    792        if (crv != CKR_OK) {
    793            goto fail;
    794        }
    795        if (lastKey != NULL) {
    796            crv = prf_update(&context, lastKey, macSize);
    797            if (crv != CKR_OK) {
    798                goto fail;
    799            }
    800            hashedData = PR_TRUE;
    801        }
    802        if (gxyKeyValue != NULL) {
    803            crv = prf_update(&context, gxyKeyValue->attrib.pValue,
    804                             gxyKeyValue->attrib.ulValueLen);
    805            if (crv != CKR_OK) {
    806                goto fail;
    807            }
    808            hashedData = PR_TRUE;
    809        }
    810        if (params->ulExtraDataLen != 0) {
    811            crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen);
    812            if (crv != CKR_OK) {
    813                goto fail;
    814            }
    815            hashedData = PR_TRUE;
    816        }
    817        /* if we haven't hashed anything yet, hash a zero */
    818        if (hashedData == PR_FALSE) {
    819            const unsigned char zero = 0;
    820            crv = prf_update(&context, &zero, 1);
    821            if (crv != CKR_OK) {
    822                goto fail;
    823            }
    824        }
    825        crv = prf_final(&context, thisKey, macSize);
    826        if (crv != CKR_OK) {
    827            goto fail;
    828        }
    829        lastKey = thisKey;
    830        thisKey += macSize;
    831    }
    832    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
    833 fail:
    834    if (gxyKeyValue) {
    835        sftk_FreeAttribute(gxyKeyValue);
    836    }
    837    if (gxyKeyObj) {
    838        sftk_FreeObject(gxyKeyObj);
    839    }
    840    if (outKeyData) {
    841        PORT_ZFree(outKeyData, outKeySize);
    842    }
    843    prf_free(&context);
    844    return crv;
    845 }
    846 
    847 /*
    848 * The final flavor of ike prf is ike_prf_plus
    849 *
    850 * It is used by ikeV2 to generate the various session keys used in the
    851 * connection. It uses the initial key and a feedback version of the prf
    852 * to generate sufficient bytes to cover all the session keys. The application
    853 * will then use CK_EXTRACT_KEY_FROM_KEY to pull out the various subkeys.
    854 * This function expects a key size to be set by the application to cover
    855 * all the keys.  Unlike ike1_prf, if no length is provided, this function
    856 * will generate a KEY_RANGE_ERROR
    857 *
    858 * This function returns (from rfc5996):
    859 * prfplus = T1 | T2 | T3 | T4 |... Tn
    860 * where:
    861 *       T1 = prf(K, S  | 0x01)
    862 *       T2 = prf(K, T1 | S | 0x02)
    863 *       T3 = prf(K, T3 | S | 0x03)
    864 *       T4 = prf(K, T4 | S | 0x04)
    865 *            .
    866 *       Tn = prf(K, T(n-1) | n)
    867 * K = inKey, S = seedKey | seedData
    868 */
    869 
    870 static CK_RV
    871 sftk_ike_prf_plus_raw(CK_SESSION_HANDLE hSession,
    872                      const unsigned char *inKeyData, CK_ULONG inKeyLen,
    873                      const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params,
    874                      unsigned char **outKeyDataPtr, unsigned int *outKeySizePtr,
    875                      unsigned int keySize)
    876 {
    877    SFTKAttribute *seedValue = NULL;
    878    SFTKObject *seedKeyObj = NULL;
    879    unsigned char *outKeyData = NULL;
    880    unsigned int outKeySize;
    881    unsigned char *thisKey;
    882    unsigned char *lastKey = NULL;
    883    unsigned char currentByte = 0;
    884    unsigned int getKeySize;
    885    unsigned int macSize;
    886    CK_RV crv;
    887    prfContext context;
    888 
    889    if (keySize == 0) {
    890        return CKR_KEY_SIZE_RANGE;
    891    }
    892 
    893    crv = prf_setup(&context, params->prfMechanism);
    894    if (crv != CKR_OK) {
    895        return crv;
    896    }
    897    /* pull in optional seedKey */
    898    if (params->bHasSeedKey) {
    899        SFTKSession *session = sftk_SessionFromHandle(hSession);
    900        if (session == NULL) {
    901            return CKR_SESSION_HANDLE_INVALID;
    902        }
    903        seedKeyObj = sftk_ObjectFromHandle(params->hSeedKey, session);
    904        sftk_FreeSession(session);
    905        if (seedKeyObj == NULL) {
    906            return CKR_KEY_HANDLE_INVALID;
    907        }
    908        seedValue = sftk_FindAttribute(seedKeyObj, CKA_VALUE);
    909        if (seedValue == NULL) {
    910            crv = CKR_KEY_HANDLE_INVALID;
    911            goto fail;
    912        }
    913    } else if (params->ulSeedDataLen == 0) {
    914        crv = CKR_ARGUMENTS_BAD;
    915        goto fail;
    916    }
    917    macSize = prf_length(&context);
    918    outKeySize = PR_ROUNDUP(keySize, macSize);
    919    outKeyData = PORT_Alloc(outKeySize);
    920    if (outKeyData == NULL) {
    921        crv = CKR_HOST_MEMORY;
    922        goto fail;
    923    }
    924 
    925    /*
    926     * this loop generates on block of the prf, basically
    927     *   Tn = prf(key, Tn-1 | S | n)
    928     *   Tn is thisKey, Tn-2 is lastKey, S is seedKey || seedData,
    929     *   key is inKey. currentByte = n-1 on entry.
    930     */
    931    thisKey = outKeyData;
    932    for (getKeySize = 0; getKeySize < keySize; getKeySize += macSize) {
    933        /* if currentByte is 255, we'll overflow when we increment it below.
    934         * This can only happen if keysize > 255*macSize. In that case
    935         * the application has asked for too much key material, so return
    936         * an error */
    937        if (currentByte == 255) {
    938            crv = CKR_KEY_SIZE_RANGE;
    939            goto fail;
    940        }
    941        crv = prf_init(&context, inKeyData, inKeyLen);
    942        if (crv != CKR_OK) {
    943            goto fail;
    944        }
    945 
    946        if (lastKey) {
    947            crv = prf_update(&context, lastKey, macSize);
    948            if (crv != CKR_OK) {
    949                goto fail;
    950            }
    951        }
    952        /* prf the key first */
    953        if (seedValue) {
    954            crv = prf_update(&context, seedValue->attrib.pValue,
    955                             seedValue->attrib.ulValueLen);
    956            if (crv != CKR_OK) {
    957                goto fail;
    958            }
    959        }
    960        /* then prf the data */
    961        if (params->ulSeedDataLen != 0) {
    962            crv = prf_update(&context, params->pSeedData,
    963                             params->ulSeedDataLen);
    964            if (crv != CKR_OK) {
    965                goto fail;
    966            }
    967        }
    968        currentByte++;
    969        crv = prf_update(&context, &currentByte, 1);
    970        if (crv != CKR_OK) {
    971            goto fail;
    972        }
    973        crv = prf_final(&context, thisKey, macSize);
    974        if (crv != CKR_OK) {
    975            goto fail;
    976        }
    977        lastKey = thisKey;
    978        thisKey += macSize;
    979    }
    980    *outKeyDataPtr = outKeyData;
    981    *outKeySizePtr = outKeySize;
    982    outKeyData = NULL; /* don't free it here, our caller will free it */
    983 fail:
    984    if (outKeyData) {
    985        PORT_ZFree(outKeyData, outKeySize);
    986    }
    987    if (seedValue) {
    988        sftk_FreeAttribute(seedValue);
    989    }
    990    if (seedKeyObj) {
    991        sftk_FreeObject(seedKeyObj);
    992    }
    993    prf_free(&context);
    994    return crv;
    995 }
    996 
    997 /*
    998 * ike prf + with code to deliever results tosoftoken objects.
    999 */
   1000 CK_RV
   1001 sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
   1002                  const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
   1003                  unsigned int keySize)
   1004 {
   1005    unsigned char *outKeyData = NULL;
   1006    unsigned int outKeySize;
   1007    CK_RV crv;
   1008 
   1009    crv = sftk_ike_prf_plus_raw(hSession, inKey->attrib.pValue,
   1010                                inKey->attrib.ulValueLen, params,
   1011                                &outKeyData, &outKeySize, keySize);
   1012    if (crv != CKR_OK) {
   1013        return crv;
   1014    }
   1015 
   1016    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
   1017    PORT_ZFree(outKeyData, outKeySize);
   1018    return crv;
   1019 }
   1020 
   1021 /* sftk_aes_xcbc_new_keys:
   1022 *
   1023 * aes xcbc creates 3 new keys from the input key. The first key will be the
   1024 * base key of the underlying cbc. The sign code hooks directly into encrypt
   1025 * so we'll have to create a full PKCS #11 key with handle for that key. The
   1026 * caller needs to delete the key when it's through setting up the context.
   1027 *
   1028 * The other two keys will be stored in the sign context until we need them
   1029 * at the end.
   1030 */
   1031 CK_RV
   1032 sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
   1033                       CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
   1034                       unsigned char *k2, unsigned char *k3)
   1035 {
   1036    SFTKObject *key = NULL;
   1037    SFTKSession *session = NULL;
   1038    SFTKObject *inKeyObj = NULL;
   1039    SFTKAttribute *inKeyValue = NULL;
   1040    CK_KEY_TYPE key_type = CKK_AES;
   1041    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
   1042    CK_BBOOL ck_true = CK_TRUE;
   1043    CK_RV crv = CKR_OK;
   1044    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
   1045    unsigned char buf[AES_BLOCK_SIZE];
   1046 
   1047    if (!slot) {
   1048        return CKR_SESSION_HANDLE_INVALID;
   1049    }
   1050 
   1051    /* get the session */
   1052    session = sftk_SessionFromHandle(hSession);
   1053    if (session == NULL) {
   1054        crv = CKR_SESSION_HANDLE_INVALID;
   1055        goto fail;
   1056    }
   1057 
   1058    inKeyObj = sftk_ObjectFromHandle(hKey, session);
   1059    if (inKeyObj == NULL) {
   1060        crv = CKR_KEY_HANDLE_INVALID;
   1061        goto fail;
   1062    }
   1063 
   1064    inKeyValue = sftk_FindAttribute(inKeyObj, CKA_VALUE);
   1065    if (inKeyValue == NULL) {
   1066        crv = CKR_KEY_HANDLE_INVALID;
   1067        goto fail;
   1068    }
   1069 
   1070    crv = sftk_aes_xcbc_get_keys(inKeyValue->attrib.pValue,
   1071                                 inKeyValue->attrib.ulValueLen, buf, k2, k3);
   1072 
   1073    if (crv != CKR_OK) {
   1074        goto fail;
   1075    }
   1076 
   1077    /*
   1078     * now lets create an object to hang the attributes off of
   1079     */
   1080    key = sftk_NewObject(slot); /* fill in the handle later */
   1081    if (key == NULL) {
   1082        crv = CKR_HOST_MEMORY;
   1083        goto fail;
   1084    }
   1085 
   1086    /* make sure we don't have any class, key_type, or value fields */
   1087    sftk_DeleteAttributeType(key, CKA_CLASS);
   1088    sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
   1089    sftk_DeleteAttributeType(key, CKA_VALUE);
   1090    sftk_DeleteAttributeType(key, CKA_SIGN);
   1091 
   1092    /* Add the class, key_type, and value */
   1093    crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
   1094    if (crv != CKR_OK) {
   1095        goto fail;
   1096    }
   1097    crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
   1098    if (crv != CKR_OK) {
   1099        goto fail;
   1100    }
   1101    crv = sftk_AddAttributeType(key, CKA_SIGN, &ck_true, sizeof(CK_BBOOL));
   1102    if (crv != CKR_OK) {
   1103        goto fail;
   1104    }
   1105    crv = sftk_AddAttributeType(key, CKA_VALUE, buf, AES_BLOCK_SIZE);
   1106    if (crv != CKR_OK) {
   1107        goto fail;
   1108    }
   1109 
   1110    /*
   1111     * finish filling in the key and link it with our global system.
   1112     */
   1113    crv = sftk_handleObject(key, session);
   1114    if (crv != CKR_OK) {
   1115        goto fail;
   1116    }
   1117    *phKey = key->handle;
   1118 fail:
   1119    if (session) {
   1120        sftk_FreeSession(session);
   1121    }
   1122 
   1123    if (inKeyValue) {
   1124        sftk_FreeAttribute(inKeyValue);
   1125    }
   1126    if (inKeyObj) {
   1127        sftk_FreeObject(inKeyObj);
   1128    }
   1129    if (key) {
   1130        sftk_FreeObject(key);
   1131    }
   1132    /* clear our CSPs */
   1133    PORT_Memset(buf, 0, sizeof(buf));
   1134    if (crv != CKR_OK) {
   1135        PORT_Memset(k2, 0, AES_BLOCK_SIZE);
   1136        PORT_Memset(k3, 0, AES_BLOCK_SIZE);
   1137    }
   1138    return crv;
   1139 }
   1140 
   1141 /*
   1142 * Helper function that tests a single prf test vector
   1143 */
   1144 static SECStatus
   1145 prf_test(CK_MECHANISM_TYPE mech,
   1146         const unsigned char *inKey, unsigned int inKeyLen,
   1147         const unsigned char *plainText, unsigned int plainTextLen,
   1148         const unsigned char *expectedResult, unsigned int expectedResultLen)
   1149 {
   1150    PRUint8 ike_computed_mac[HASH_LENGTH_MAX];
   1151    prfContext context;
   1152    unsigned int macSize;
   1153    CK_RV crv;
   1154 
   1155    crv = prf_setup(&context, mech);
   1156    if (crv != CKR_OK) {
   1157        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1158        return SECFailure;
   1159    }
   1160    macSize = prf_length(&context);
   1161    crv = prf_init(&context, inKey, inKeyLen);
   1162    if (crv != CKR_OK) {
   1163        goto fail;
   1164    }
   1165    crv = prf_update(&context, plainText, plainTextLen);
   1166    if (crv != CKR_OK) {
   1167        goto fail;
   1168    }
   1169    crv = prf_final(&context, ike_computed_mac, macSize);
   1170    if (crv != CKR_OK) {
   1171        goto fail;
   1172    }
   1173 
   1174    if (macSize != expectedResultLen) {
   1175        goto fail;
   1176    }
   1177    if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) {
   1178        goto fail;
   1179    }
   1180 
   1181    /* only do the alignment if the plaintext is long enough */
   1182    if (plainTextLen <= macSize) {
   1183        return SECSuccess;
   1184    }
   1185    prf_free(&context);
   1186    /* do it again, but this time tweak with the alignment */
   1187    crv = prf_init(&context, inKey, inKeyLen);
   1188    if (crv != CKR_OK) {
   1189        goto fail;
   1190    }
   1191    crv = prf_update(&context, plainText, 1);
   1192    if (crv != CKR_OK) {
   1193        goto fail;
   1194    }
   1195    crv = prf_update(&context, &plainText[1], macSize);
   1196    if (crv != CKR_OK) {
   1197        goto fail;
   1198    }
   1199    crv = prf_update(&context, &plainText[1 + macSize], plainTextLen - (macSize + 1));
   1200    if (crv != CKR_OK) {
   1201        goto fail;
   1202    }
   1203    crv = prf_final(&context, ike_computed_mac, macSize);
   1204    if (crv != CKR_OK) {
   1205        goto fail;
   1206    }
   1207    if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) {
   1208        goto fail;
   1209    }
   1210    prf_free(&context);
   1211    return SECSuccess;
   1212 fail:
   1213    prf_free(&context);
   1214    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1215    return SECFailure;
   1216 }
   1217 
   1218 /*
   1219 * FIPS Power up Self Tests for IKE. This is in this function so it
   1220 * can access the private prf_ functions here. It's called out of fipstest.c
   1221 */
   1222 SECStatus
   1223 sftk_fips_IKE_PowerUpSelfTests(void)
   1224 {
   1225    /* PRF known test vectors */
   1226    static const PRUint8 ike_xcbc_known_key[] = {
   1227        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   1228        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   1229    };
   1230    static const PRUint8 ike_xcbc_known_plain_text[] = {
   1231        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   1232        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   1233    };
   1234    static const PRUint8 ike_xcbc_known_mac[] = {
   1235        0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
   1236        0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63
   1237    };
   1238    /* test 2 uses the same key as test 1 */
   1239    static const PRUint8 ike_xcbc_known_plain_text_2[] = {
   1240        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   1241        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   1242        0x10, 0x11, 0x12, 0x13
   1243    };
   1244    static const PRUint8 ike_xcbc_known_mac_2[] = {
   1245        0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
   1246        0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08
   1247    };
   1248    static const PRUint8 ike_xcbc_known_key_3[] = {
   1249        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   1250        0x08, 0x09
   1251    };
   1252    /* test 3 uses the same plaintest as test 2 */
   1253    static const PRUint8 ike_xcbc_known_mac_3[] = {
   1254        0x0f, 0xa0, 0x87, 0xaf, 0x7d, 0x86, 0x6e, 0x76,
   1255        0x53, 0x43, 0x4e, 0x60, 0x2f, 0xdd, 0xe8, 0x35
   1256    };
   1257    static const PRUint8 ike_xcbc_known_key_4[] = {
   1258        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   1259        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   1260        0xed, 0xcb
   1261    };
   1262    /* test 4 uses the same plaintest as test 2 */
   1263    static const PRUint8 ike_xcbc_known_mac_4[] = {
   1264        0x8c, 0xd3, 0xc9, 0x3a, 0xe5, 0x98, 0xa9, 0x80,
   1265        0x30, 0x06, 0xff, 0xb6, 0x7c, 0x40, 0xe9, 0xe4
   1266    };
   1267    static const PRUint8 ike_sha1_known_key[] = {
   1268        0x59, 0x98, 0x2b, 0x5b, 0xa5, 0x7e, 0x62, 0xc0,
   1269        0x46, 0x0d, 0xef, 0xc7, 0x1e, 0x18, 0x64, 0x63
   1270    };
   1271    static const PRUint8 ike_sha1_known_plain_text[] = {
   1272        0x1c, 0x07, 0x32, 0x1a, 0x9a, 0x7e, 0x41, 0xcd,
   1273        0x88, 0x0c, 0xa3, 0x7a, 0xdb, 0x10, 0xc7, 0x3b,
   1274        0xf0, 0x0e, 0x7a, 0xe3, 0xcf, 0xc6, 0xfd, 0x8b,
   1275        0x51, 0xbc, 0xe2, 0xb9, 0x90, 0xe6, 0xf2, 0x01
   1276    };
   1277    static const PRUint8 ike_sha1_known_mac[] = {
   1278        0x0c, 0x2a, 0xf3, 0x42, 0x97, 0x15, 0x62, 0x1d,
   1279        0x2a, 0xad, 0xc9, 0x94, 0x5a, 0x90, 0x26, 0xfa,
   1280        0xc7, 0x91, 0xe2, 0x4b
   1281    };
   1282    static const PRUint8 ike_sha256_known_key[] = {
   1283        0x9d, 0xa2, 0xd5, 0x8f, 0x57, 0xf0, 0x39, 0xf9,
   1284        0x20, 0x4e, 0x0d, 0xd0, 0xef, 0x04, 0xf3, 0x72
   1285    };
   1286    static const PRUint8 ike_sha256_known_plain_text[] = {
   1287        0x33, 0xf1, 0x7a, 0xfc, 0xb6, 0x13, 0x4c, 0xbf,
   1288        0x1c, 0xab, 0x59, 0x87, 0x7d, 0x42, 0xdb, 0x35,
   1289        0x82, 0x22, 0x6e, 0xff, 0x74, 0xdd, 0x37, 0xeb,
   1290        0x8b, 0x75, 0xe6, 0x75, 0x64, 0x5f, 0xc1, 0x69
   1291    };
   1292    static const PRUint8 ike_sha256_known_mac[] = {
   1293        0x80, 0x4b, 0x4a, 0x1e, 0x0e, 0xc5, 0x93, 0xcf,
   1294        0xb6, 0xe4, 0x54, 0x52, 0x41, 0x49, 0x39, 0x6d,
   1295        0xe2, 0x34, 0xd0, 0xda, 0xe2, 0x9f, 0x34, 0xa8,
   1296        0xfd, 0xb5, 0xf9, 0xaf, 0xe7, 0x6e, 0xa6, 0x52
   1297    };
   1298    static const PRUint8 ike_sha384_known_key[] = {
   1299        0xce, 0xc8, 0x9d, 0x84, 0x5a, 0xdd, 0x83, 0xef,
   1300        0xce, 0xbd, 0x43, 0xab, 0x71, 0xd1, 0x7d, 0xb9
   1301    };
   1302    static const PRUint8 ike_sha384_known_plain_text[] = {
   1303        0x17, 0x24, 0xdb, 0xd8, 0x93, 0x52, 0x37, 0x64,
   1304        0xbf, 0xef, 0x8c, 0x6f, 0xa9, 0x27, 0x85, 0x6f,
   1305        0xcc, 0xfb, 0x77, 0xae, 0x25, 0x43, 0x58, 0xcc,
   1306        0xe2, 0x9c, 0x27, 0x69, 0xa3, 0x29, 0x15, 0xc1
   1307    };
   1308    static const PRUint8 ike_sha384_known_mac[] = {
   1309        0x6e, 0x45, 0x14, 0x61, 0x0b, 0xf8, 0x2d, 0x0a,
   1310        0xb7, 0xbf, 0x02, 0x60, 0x09, 0x6f, 0x61, 0x46,
   1311        0xa1, 0x53, 0xc7, 0x12, 0x07, 0x1a, 0xbb, 0x63,
   1312        0x3c, 0xed, 0x81, 0x3c, 0x57, 0x21, 0x56, 0xc7,
   1313        0x83, 0xe3, 0x68, 0x74, 0xa6, 0x5a, 0x64, 0x69,
   1314        0x0c, 0xa7, 0x01, 0xd4, 0x0d, 0x56, 0xea, 0x18
   1315    };
   1316    static const PRUint8 ike_sha512_known_key[] = {
   1317        0xac, 0xad, 0xc6, 0x31, 0x4a, 0x69, 0xcf, 0xcd,
   1318        0x4e, 0x4a, 0xd1, 0x77, 0x18, 0xfe, 0xa7, 0xce
   1319    };
   1320    static const PRUint8 ike_sha512_known_plain_text[] = {
   1321        0xb1, 0x5a, 0x9c, 0xfc, 0xe8, 0xc8, 0xd7, 0xea,
   1322        0xb8, 0x79, 0xd6, 0x24, 0x30, 0x29, 0xd4, 0x01,
   1323        0x88, 0xd3, 0xb7, 0x40, 0x87, 0x5a, 0x6a, 0xc6,
   1324        0x2f, 0x56, 0xca, 0xc4, 0x37, 0x7e, 0x2e, 0xdd
   1325    };
   1326    static const PRUint8 ike_sha512_known_mac[] = {
   1327        0xf0, 0x5a, 0xa0, 0x36, 0xdf, 0xce, 0x45, 0xa5,
   1328        0x58, 0xd4, 0x04, 0x18, 0xde, 0xa9, 0x80, 0x96,
   1329        0xe5, 0x19, 0xbc, 0x78, 0x41, 0xe3, 0xdb, 0x3d,
   1330        0xd9, 0x36, 0x58, 0xd1, 0x18, 0xc3, 0xe8, 0x3b,
   1331        0x50, 0x2f, 0x39, 0x8e, 0xcb, 0x13, 0x61, 0xec,
   1332        0x77, 0xd3, 0x8a, 0x88, 0x55, 0xef, 0xff, 0x40,
   1333        0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e,
   1334        0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b
   1335    };
   1336    static const PRUint8 ike_known_sha256_prf_plus[] = {
   1337        0xe6, 0xf1, 0x9b, 0x4a, 0x02, 0xe9, 0x73, 0x72,
   1338        0x93, 0x9f, 0xdb, 0x46, 0x1d, 0xb1, 0x49, 0xcb,
   1339        0x53, 0x08, 0x98, 0x3d, 0x41, 0x36, 0xfa, 0x8b,
   1340        0x47, 0x04, 0x49, 0x11, 0x0d, 0x6e, 0x96, 0x1d,
   1341        0xab, 0xbe, 0x94, 0x28, 0xa0, 0xb7, 0x9c, 0xa3,
   1342        0x29, 0xe1, 0x40, 0xf8, 0xf8, 0x88, 0xb9, 0xb5,
   1343        0x40, 0xd4, 0x54, 0x4d, 0x25, 0xab, 0x94, 0xd4,
   1344        0x98, 0xd8, 0x00, 0xbf, 0x6f, 0xef, 0xe8, 0x39
   1345    };
   1346    SECStatus rv;
   1347    CK_RV crv;
   1348    unsigned char *outKeyData = NULL;
   1349    unsigned int outKeySize;
   1350    CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike_params;
   1351 
   1352    rv = prf_test(CKM_AES_XCBC_MAC,
   1353                  ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
   1354                  ike_xcbc_known_plain_text, sizeof(ike_xcbc_known_plain_text),
   1355                  ike_xcbc_known_mac, sizeof(ike_xcbc_known_mac));
   1356    if (rv != SECSuccess)
   1357        return rv;
   1358    rv = prf_test(CKM_AES_XCBC_MAC,
   1359                  ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
   1360                  ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
   1361                  ike_xcbc_known_mac_2, sizeof(ike_xcbc_known_mac_2));
   1362    if (rv != SECSuccess)
   1363        return rv;
   1364    rv = prf_test(CKM_AES_XCBC_MAC,
   1365                  ike_xcbc_known_key_3, sizeof(ike_xcbc_known_key_3),
   1366                  ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
   1367                  ike_xcbc_known_mac_3, sizeof(ike_xcbc_known_mac_3));
   1368    if (rv != SECSuccess)
   1369        return rv;
   1370    rv = prf_test(CKM_AES_XCBC_MAC,
   1371                  ike_xcbc_known_key_4, sizeof(ike_xcbc_known_key_4),
   1372                  ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
   1373                  ike_xcbc_known_mac_4, sizeof(ike_xcbc_known_mac_4));
   1374    if (rv != SECSuccess)
   1375        return rv;
   1376    rv = prf_test(CKM_SHA_1_HMAC,
   1377                  ike_sha1_known_key, sizeof(ike_sha1_known_key),
   1378                  ike_sha1_known_plain_text, sizeof(ike_sha1_known_plain_text),
   1379                  ike_sha1_known_mac, sizeof(ike_sha1_known_mac));
   1380    if (rv != SECSuccess)
   1381        return rv;
   1382    rv = prf_test(CKM_SHA256_HMAC,
   1383                  ike_sha256_known_key, sizeof(ike_sha256_known_key),
   1384                  ike_sha256_known_plain_text,
   1385                  sizeof(ike_sha256_known_plain_text),
   1386                  ike_sha256_known_mac, sizeof(ike_sha256_known_mac));
   1387    if (rv != SECSuccess)
   1388        return rv;
   1389    rv = prf_test(CKM_SHA384_HMAC,
   1390                  ike_sha384_known_key, sizeof(ike_sha384_known_key),
   1391                  ike_sha384_known_plain_text,
   1392                  sizeof(ike_sha384_known_plain_text),
   1393                  ike_sha384_known_mac, sizeof(ike_sha384_known_mac));
   1394    if (rv != SECSuccess)
   1395        return rv;
   1396    rv = prf_test(CKM_SHA512_HMAC,
   1397                  ike_sha512_known_key, sizeof(ike_sha512_known_key),
   1398                  ike_sha512_known_plain_text,
   1399                  sizeof(ike_sha512_known_plain_text),
   1400                  ike_sha512_known_mac, sizeof(ike_sha512_known_mac));
   1401 
   1402    ike_params.prfMechanism = CKM_SHA256_HMAC;
   1403    ike_params.bHasSeedKey = PR_FALSE;
   1404    ike_params.hSeedKey = CK_INVALID_HANDLE;
   1405    ike_params.pSeedData = (CK_BYTE_PTR)ike_sha256_known_plain_text;
   1406    ike_params.ulSeedDataLen = sizeof(ike_sha256_known_plain_text);
   1407    crv = sftk_ike_prf_plus_raw(CK_INVALID_HANDLE, ike_sha256_known_key,
   1408                                sizeof(ike_sha256_known_key), &ike_params,
   1409                                &outKeyData, &outKeySize, 64);
   1410    if ((crv != CKR_OK) ||
   1411        (outKeySize != sizeof(ike_known_sha256_prf_plus)) ||
   1412        (PORT_Memcmp(outKeyData, ike_known_sha256_prf_plus,
   1413                     sizeof(ike_known_sha256_prf_plus)) != 0)) {
   1414        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1415        return SECFailure;
   1416    }
   1417    PORT_ZFree(outKeyData, outKeySize);
   1418    return rv;
   1419 }