+static int ssl_security_default_callback(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex)
+ {
+ int level, minbits;
+ static const int minbits_table[5] = {80, 112, 128, 192, 256};
+ if (ctx)
+ level = SSL_CTX_get_security_level(ctx);
+ else
+ level = SSL_get_security_level(s);
+ /* Level 0: anything goes */
+ if (level <= 0)
+ return 1;
+ if (level > 5)
+ level = 5;
+ minbits = minbits_table[level - 1];
+ switch (op)
+ {
+ case SSL_SECOP_CIPHER_SUPPORTED:
+ case SSL_SECOP_CIPHER_SHARED:
+ case SSL_SECOP_CIPHER_CHECK:
+ {
+ const SSL_CIPHER *c = other;
+ /* No ciphers below security level */
+ if (bits < minbits)
+ return 0;
+ /* No SSLv2 ciphers */
+ if ((SSL_CIPHER_get_id(c) >> 24) == 0x2)
+ return 0;
+ /* No unauthenticated ciphersuites */
+ if (c->algorithm_auth & SSL_aNULL)
+ return 0;
+ /* No MD5 mac ciphersuites */
+ if (c->algorithm_mac & SSL_MD5)
+ return 0;
+ /* SHA1 HMAC is 160 bits of security */
+ if (minbits > 160 && c->algorithm_mac & SSL_SHA1)
+ return 0;
+ /* Level 2: no RC4 */
+ if (level >= 2 && c->algorithm_enc == SSL_RC4)
+ return 0;
+ /* Level 3: forward secure ciphersuites only */
+ if (level >= 3 && !(c->algorithm_mkey & (SSL_kEDH|SSL_kEECDH)))
+ return 0;
+ break;
+ }
+ case SSL_SECOP_VERSION:
+ /* SSLv2 allowed only on level zero */
+ if (nid == SSL2_VERSION)
+ return 0;
+ /* SSLv3 not allowed on level 2 */
+ if (nid <= SSL3_VERSION && level >= 2)
+ return 0;
+ /* TLS v1.1 and above only for level 3 */
+ if (nid <= TLS1_VERSION && level >= 3)
+ return 0;
+ /* TLS v1.2 only for level 4 and above */
+ if (nid <= TLS1_1_VERSION && level >= 4)
+ return 0;
+ break;
+
+ case SSL_SECOP_COMPRESSION:
+ if (level >= 2)
+ return 0;
+ break;
+ case SSL_SECOP_TICKET:
+ if (level >= 3)
+ return 0;
+ break;
+ case SSL_SECOP_SSL2_COMPAT:
+ /* SSLv2 compatible client hello only for level zero */
+ return 0;
+ default:
+ if (bits < minbits)
+ return 0;
+ }
+ return 1;
+ }
+
+int ssl_security(SSL *s, int op, int bits, int nid, void *other)
+ {
+ return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex);
+ }
+
+int ssl_ctx_security(SSL_CTX *ctx, int op, int bits, int nid, void *other)
+ {
+ return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other, ctx->cert->sec_ex);
+ }