static void ssl_cipher_apply_rule(unsigned long cipher_id, unsigned long alg_mkey, unsigned long alg_auth, unsigned long alg_enc, unsigned long alg_mac, unsigned long alg_ssl, unsigned long algo_strength, int rule, int strength_bits, CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) { CIPHER_ORDER *head, *tail, *curr, *curr2, *last; const SSL_CIPHER *cp; int reverse = 0; #ifdef CIPHER_DEBUG printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d)\n", rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits); #endif if (rule == CIPHER_DEL) reverse = 1; /* needed to maintain sorting between currently deleted ciphers */ head = *head_p; tail = *tail_p; if (reverse) { curr = tail; last = head; } else { curr = head; last = tail; } curr2 = curr; for (;;) { if ((curr == NULL) || (curr == last)) break; curr = curr2; curr2 = reverse ? curr->prev : curr->next; cp = curr->cipher; /* * Selection criteria is either the value of strength_bits * or the algorithms used. */ if (strength_bits >= 0) { if (strength_bits != cp->strength_bits) continue; } else { #ifdef CIPHER_DEBUG printf("\nName: %s:\nAlgo = %08lx/%08lx/%08lx/%08lx/%08lx Algo_strength = %08lx\n", cp->name, cp->algorithm_mkey, cp->algorithm_auth, cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl, cp->algo_strength); #endif if (alg_mkey && !(alg_mkey & cp->algorithm_mkey)) continue; if (alg_auth && !(alg_auth & cp->algorithm_auth)) continue; if (alg_enc && !(alg_enc & cp->algorithm_enc)) continue; if (alg_mac && !(alg_mac & cp->algorithm_mac)) continue; if (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) continue; if ((algo_strength & SSL_EXP_MASK) && !(algo_strength & SSL_EXP_MASK & cp->algo_strength)) continue; if ((algo_strength & SSL_STRONG_MASK) && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength)) continue; } #ifdef CIPHER_DEBUG printf("Action = %d\n", rule); #endif /* add the cipher if it has not been added yet. */ if (rule == CIPHER_ADD) { /* reverse == 0 */ if (!curr->active) { ll_append_tail(&head, curr, &tail); curr->active = 1; } } /* Move the added cipher to this location */ else if (rule == CIPHER_ORD) { /* reverse == 0 */ if (curr->active) { ll_append_tail(&head, curr, &tail); } } else if (rule == CIPHER_DEL) { /* reverse == 1 */ if (curr->active) { /* most recently deleted ciphersuites get best positions * for any future CIPHER_ADD (note that the CIPHER_DEL loop * works in reverse to maintain the order) */ ll_append_head(&head, curr, &tail); curr->active = 0; } } else if (rule == CIPHER_KILL) { /* reverse == 0 */ if (head == curr) head = curr->next; else curr->prev->next = curr->next; if (tail == curr) tail = curr->prev; curr->active = 0; if (curr->next != NULL) curr->next->prev = curr->prev; if (curr->prev != NULL) curr->prev->next = curr->next; curr->next = NULL; curr->prev = NULL; } } *head_p = head; *tail_p = tail; }
/* ssl_cipher_apply_rule applies the rule type |rule| to ciphers matching its * parameters in the linked list from |*head_p| to |*tail_p|. It writes the new * head and tail of the list to |*head_p| and |*tail_p|, respectively. * * - If |cipher_id| is non-zero, only that cipher is selected. * - Otherwise, if |strength_bits| is non-negative, it selects ciphers * of that strength. * - Otherwise, it selects ciphers that match each bitmasks in |alg_*| and * |algo_strength|. */ static void ssl_cipher_apply_rule( uint32_t cipher_id, uint32_t alg_mkey, uint32_t alg_auth, uint32_t alg_enc, uint32_t alg_mac, uint32_t alg_ssl, uint32_t algo_strength, int rule, int strength_bits, int in_group, CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) { CIPHER_ORDER *head, *tail, *curr, *next, *last; const SSL_CIPHER *cp; int reverse = 0; if (cipher_id == 0 && strength_bits == -1 && (alg_mkey == 0 || alg_auth == 0 || alg_enc == 0 || alg_mac == 0 || alg_ssl == 0 || algo_strength == 0)) { /* The rule matches nothing, so bail early. */ return; } if (rule == CIPHER_DEL) { /* needed to maintain sorting between currently deleted ciphers */ reverse = 1; } head = *head_p; tail = *tail_p; if (reverse) { next = tail; last = head; } else { next = head; last = tail; } curr = NULL; for (;;) { if (curr == last) { break; } curr = next; if (curr == NULL) { break; } next = reverse ? curr->prev : curr->next; cp = curr->cipher; /* Selection criteria is either a specific cipher, the value of * |strength_bits|, or the algorithms used. */ if (cipher_id != 0) { if (cipher_id != cp->id) { continue; } } else if (strength_bits >= 0) { if (strength_bits != cp->strength_bits) { continue; } } else if (!(alg_mkey & cp->algorithm_mkey) || !(alg_auth & cp->algorithm_auth) || !(alg_enc & cp->algorithm_enc) || !(alg_mac & cp->algorithm_mac) || !(alg_ssl & cp->algorithm_ssl) || !(algo_strength & cp->algo_strength)) { continue; } /* add the cipher if it has not been added yet. */ if (rule == CIPHER_ADD) { /* reverse == 0 */ if (!curr->active) { ll_append_tail(&head, curr, &tail); curr->active = 1; curr->in_group = in_group; } } /* Move the added cipher to this location */ else if (rule == CIPHER_ORD) { /* reverse == 0 */ if (curr->active) { ll_append_tail(&head, curr, &tail); curr->in_group = 0; } } else if (rule == CIPHER_DEL) { /* reverse == 1 */ if (curr->active) { /* most recently deleted ciphersuites get best positions * for any future CIPHER_ADD (note that the CIPHER_DEL loop * works in reverse to maintain the order) */ ll_append_head(&head, curr, &tail); curr->active = 0; curr->in_group = 0; } } else if (rule == CIPHER_KILL) { /* reverse == 0 */ if (head == curr) { head = curr->next; } else { curr->prev->next = curr->next; } if (tail == curr) { tail = curr->prev; } curr->active = 0; if (curr->next != NULL) { curr->next->prev = curr->prev; } if (curr->prev != NULL) { curr->prev->next = curr->next; } curr->next = NULL; curr->prev = NULL; } } *head_p = head; *tail_p = tail; }