Ejemplo n.º 1
0
/*
** Save away write data that is trying to be written before the security
** handshake has been completed. When the handshake is completed, we will
** flush this data out.
** Caller must hold xmitBufLock
*/
SECStatus 
ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
{
    SECStatus    rv;

    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
    rv = sslBuffer_Append(&ss->pendingBuf, data, len);
    SSL_TRC(5, ("%d: SSL[%d]: saving %u bytes of data (%u total saved so far)",
		 SSL_GETPID(), ss->fd, len, ss->pendingBuf.len));
    return rv;
}
Ejemplo n.º 2
0
static SECStatus
ssl_CallCustomExtensionSenders(sslSocket *ss, sslBuffer *buf,
                               SSLHandshakeType message)
{
    sslBuffer tail = SSL_BUFFER_EMPTY;
    SECStatus rv;
    PRCList *cursor;

    /* Save any extensions that want to be last. */
    if (ss->xtnData.lastXtnOffset) {
        rv = sslBuffer_Append(&tail, buf->buf + ss->xtnData.lastXtnOffset,
                              buf->len - ss->xtnData.lastXtnOffset);
        if (rv != SECSuccess) {
            return SECFailure;
        }
        buf->len = ss->xtnData.lastXtnOffset;
    }

    /* Reserve the maximum amount of space possible. */
    rv = sslBuffer_Grow(buf, 65535);
    if (rv != SECSuccess) {
        return SECFailure;
    }

    for (cursor = PR_NEXT_LINK(&ss->extensionHooks);
         cursor != &ss->extensionHooks;
         cursor = PR_NEXT_LINK(cursor)) {
        sslCustomExtensionHooks *hook =
            (sslCustomExtensionHooks *)cursor;
        PRBool append = PR_FALSE;
        unsigned int len = 0;

        if (hook->writer) {
            /* The writer writes directly into |buf|.  Provide space that allows
             * for the existing extensions, any tail, plus type and length. */
            unsigned int space = buf->space - (buf->len + tail.len + 4);
            append = (*hook->writer)(ss->fd, message,
                                     buf->buf + buf->len + 4, &len, space,
                                     hook->writerArg);
            if (len > space) {
                PORT_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR);
                goto loser;
            }
        }
        if (!append) {
            continue;
        }

        rv = sslBuffer_AppendNumber(buf, hook->type, 2);
        if (rv != SECSuccess) {
            goto loser; /* Code already set. */
        }
        rv = sslBuffer_AppendNumber(buf, len, 2);
        if (rv != SECSuccess) {
            goto loser; /* Code already set. */
        }
        buf->len += len;

        if (message == ssl_hs_client_hello ||
            message == ssl_hs_certificate_request) {
            ss->xtnData.advertised[ss->xtnData.numAdvertised++] = hook->type;
        }
    }

    rv = sslBuffer_Append(buf, tail.buf, tail.len);
    if (rv != SECSuccess) {
        goto loser; /* Code already set. */
    }

    sslBuffer_Clear(&tail);
    return SECSuccess;

loser:
    sslBuffer_Clear(&tail);
    return SECFailure;
}
Ejemplo n.º 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;
}