selene_error_t *sln_cryptor_osx_cc_create(selene_t *s, int encrypt, sln_cipher_e type, const char *key, const char *iv, sln_cryptor_t **p_enc) { CCCryptorStatus rv; CCCryptorRef cryptor; size_t keylen; CCAlgorithm alg; CCOperation op; if (encrypt) { op = kCCEncrypt; } else { op = kCCDecrypt; } switch (type) { case SLN_CIPHER_AES_128_CBC: alg = kCCAlgorithmAES128; keylen = kCCKeySizeAES128; break; case SLN_CIPHER_AES_256_CBC: /* TODO: it is not clear from the docs why this is named AES-128, but if * you * pass in a key size that is for AES-256, it works (?????) as if it was * in AES-256 mode (!!!!!) */ alg = kCCAlgorithmAES128; keylen = kCCKeySizeAES256; break; case SLN_CIPHER_RC4: alg = kCCAlgorithmRC4; keylen = SLN_CIPHER_RC4_128_KEY_LENGTH; break; default: return selene_error_createf(SELENE_ENOTIMPL, "Unsupported cipher type: %d", type); } rv = CCCryptorCreate(op, alg, 0, key, keylen, iv, &cryptor); if (rv != kCCSuccess) { return selene_error_createf( SELENE_EIO, "CCCryptorCreate failed CCCryptorStatus=%d", rv); } else { sln_cryptor_t *enc = sln_alloc(s, sizeof(sln_cryptor_t)); enc->s = s; enc->baton = cryptor; enc->type = type; *p_enc = enc; } return SELENE_SUCCESS; }
selene_error_t *sln_tls_serialize_header(selene_t *s, sln_msg_tls_t *tls, sln_bucket_t **p_b) { sln_bucket_t *b = NULL; size_t len = 5; sln_bucket_create_empty(s->alloc, &b, len); switch (tls->content_type) { case SLN_CONTENT_TYPE_CHANGE_CIPHER_SPEC: b->data[0] = 0x14; break; case SLN_CONTENT_TYPE_ALERT: b->data[0] = 0x15; break; case SLN_CONTENT_TYPE_HANDSHAKE: b->data[0] = 0x16; break; case SLN_CONTENT_TYPE_APPLICATION: b->data[0] = 0x17; break; default: return selene_error_createf(SELENE_EINVAL, "Unknown content type: %d", tls->content_type); } b->data[1] = tls->version_major; b->data[2] = tls->version_minor; b->data[3] = tls->length >> 8; b->data[4] = tls->length; *p_b = b; return SELENE_SUCCESS; }
selene_error_t* selene_conf_ca_trusted_cert_add(selene_conf_t *conf, const char *certificate) { /* TOOD: replace with native x509 :( )*/ BIO *bio = BIO_new(BIO_s_mem()); int r = BIO_write(bio, certificate, strlen(certificate)); if (r <= 0) { BIO_free(bio); return selene_error_createf(SELENE_ENOMEM, "Attempting to parse CA certificate, BIO_write returned: %d", r); } X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (!x509) { BIO_free(bio); /* TODO: better error messages */ return selene_error_create(SELENE_ENOMEM, "Attempting to parse CA certificate, PEM_read_bio_X509 failed."); } BIO_free(bio); X509_STORE_add_cert(conf->trusted_cert_store, x509); return SELENE_SUCCESS; }
selene_error_t *selene_conf_cert_chain_add(selene_conf_t *conf, const char *certificate, const char *pkey) { selene_cert_chain_t *certs = NULL; BIO *bio = BIO_new(BIO_s_mem()); int r = BIO_write(bio, certificate, strlen(certificate)); if (r <= 0) { BIO_free(bio); return selene_error_createf( SELENE_ENOMEM, "Attempting to parse Cert Chain certificate, BIO_write returned: %d", r); } /* TODO: private key */ SELENE_ERR(read_certificate_chain(conf, bio, &certs)); SLN_ARRAY_PUSH(conf->certs, selene_cert_chain_t *) = certs; return SELENE_SUCCESS; }