/* ** 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; }
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; }
/* * 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; }