Example #1
1
err_status_t
srtp_validate() {
  unsigned char test_key[30] = {
    0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
    0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
    0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
    0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
  };
  uint8_t srtp_plaintext_ref[28] = {
    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
    0xab, 0xab, 0xab, 0xab
  };
  uint8_t srtp_plaintext[38] = {
    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
    0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
  uint8_t srtp_ciphertext[38] = {
    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
    0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
    0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15, 
    0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
    0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
  };
  srtp_t srtp_snd, srtp_recv;
  err_status_t status;
  int len;
  srtp_policy_t policy;
  
  /*
   * create a session with a single stream using the default srtp
   * policy and with the SSRC value 0xcafebabe
   */
  crypto_policy_set_rtp_default(&policy.rtp);
  crypto_policy_set_rtcp_default(&policy.rtcp);
  policy.ssrc.type  = ssrc_specific;
  policy.ssrc.value = 0xcafebabe;
  policy.key  = test_key;
  policy.next = NULL;

  status = srtp_create(&srtp_snd, &policy);
  if (status)
    return status;
 
  /* 
   * protect plaintext, then compare with ciphertext 
   */
  len = 28;
  status = srtp_protect(srtp_snd, srtp_plaintext, &len);
  if (status || (len != 38))
    return err_status_fail;

  debug_print(mod_driver, "ciphertext:\n  %s", 	      
	      octet_string_hex_string(srtp_plaintext, len));
  debug_print(mod_driver, "ciphertext reference:\n  %s", 	      
	      octet_string_hex_string(srtp_ciphertext, len));

  if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
    return err_status_fail;
  
  /*
   * create a receiver session context comparable to the one created
   * above - we need to do this so that the replay checking doesn't
   * complain
   */
  status = srtp_create(&srtp_recv, &policy);
  if (status)
    return status;

  /*
   * unprotect ciphertext, then compare with plaintext 
   */
  status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
  if (status || (len != 28))
    return status;
  
  if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
    return err_status_fail;

  return err_status_ok;
}
Example #2
0
bool SrtpChannel::configureSrtpSession(srtp_t *session, const char* key,
        enum TransmissionType type) {
    srtp_policy_t policy;
    memset(&policy, 0, sizeof(policy));
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    if (type == SENDING) {
        policy.ssrc.type = ssrc_any_outbound;
    } else {

        policy.ssrc.type = ssrc_any_inbound;
    }

    policy.ssrc.value = 0;
    policy.window_size = 1024;
    policy.allow_repeat_tx = 1;
    policy.next = NULL;
    //ELOG_DEBUG("auth_tag_len %d", policy.rtp.auth_tag_len);

    gsize len = 0;
    uint8_t *akey = (uint8_t*) g_base64_decode((gchar*) key, &len);
    ELOG_DEBUG("set master key/salt to %s/", octet_string_hex_string(akey, 16));
    // allocate and initialize the SRTP session
    policy.key = akey;
    int res = srtp_create(session, &policy);
    if (res!=0){
      ELOG_ERROR("Failed to create srtp session with %s, %d", octet_string_hex_string(akey, 16), res);
    }
    return res!=0? false:true;
}
Example #3
0
srtpw_err_status_t srtpw_validate_key(unsigned char *input_key)
{
    char key[SRTP_MAX_KEY_LEN];
    int len;

    /*
     * read key from hexadecimal  into an octet string
     */
    len = hex_string_to_octet_string((char *)key, (char *)input_key, SRTP_MASTER_KEY_LEN*2);

    /* check that hex string is the right length */
    if (len < SRTP_MASTER_KEY_LEN*2)
    {
        srtpw_log(err_level_error,
                  "error: too few digits in key/salt "
                  "(should be %d hexadecimal digits, found %d)\n",
                  SRTP_MASTER_KEY_LEN*2, len);
        return srtpw_err_status_bad_param;
    }
    if (strlen((const char *)input_key) > SRTP_MASTER_KEY_LEN*2)
    {
        srtpw_log(err_level_error,
                  "error: too many digits in key/salt "
                  "(should be %d hexadecimal digits, found %u)\n",
                  SRTP_MASTER_KEY_LEN*2, (unsigned)strlen((const char *)input_key));
        return srtpw_err_status_bad_param;
    }

    srtpw_log(err_level_info,"set master key/salt to %s/", octet_string_hex_string(key, SRTP_MASTERKEY_LEN));
    srtpw_log(err_level_info,"%s\n", octet_string_hex_string(key+SRTP_MASTERKEY_LEN, SRTP_MASTERSALT_LEN));
    return srtpw_err_status_ok;

}
Example #4
0
err_status_t
sha1_test_case_validate(const hash_test_case_t *test_case) {
  sha1_ctx_t ctx;
  uint32_t hash_value[5];

  if (test_case == NULL)
    return err_status_bad_param;

  if (test_case->hash_len != 20)
    return err_status_bad_param;
  if (test_case->data_len > MAX_HASH_DATA_LEN)
    return err_status_bad_param;

  sha1_init(&ctx);
  sha1_update(&ctx, test_case->data, test_case->data_len);
  sha1_final(&ctx, hash_value);
  if (0 == memcmp(test_case->hash, hash_value, 20)) {
#if VERBOSE
    printf("PASSED: reference value: %s\n", 
	   octet_string_hex_string((const uint8_t *)test_case->hash, 20));
    printf("PASSED: computed value:  %s\n", 
	   octet_string_hex_string((const uint8_t *)hash_value, 20));   
#endif 
    return err_status_ok;
  }

  printf("reference value: %s\n", 
	 octet_string_hex_string((const uint8_t *)test_case->hash, 20));
  printf("computed value:  %s\n", 
	 octet_string_hex_string((const uint8_t *)hash_value, 20));

  return err_status_algo_fail;
  
}
Example #5
0
err_status_t
null_enc(void *key,            
	 const void *clear,          
	 unsigned clear_len,       
	 void *iv,             
	 void *opaque,         
	 unsigned *opaque_len) {
  int i;
  unsigned char *auth_tag;
  unsigned char *init_vec = iv;

  /* check if we're doing authentication only */
  if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
      
      /* perform authentication only */

  } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
    
    /*
     * bad parameter - we expect either all three pointers to be NULL,
     * or none of those pointers to be NULL 
     */
    return err_status_fail;

  } else {

#if DEBUG
    printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
    printf("NULL_TAG_LEN:  %d\n", NULL_TAG_LEN);
    printf("plaintext len:  %d\n", *opaque_len);
#endif
    for (i=0; i < IV_LEN; i++)
      init_vec[i] = i + (i * 16);
#if DEBUG
    printf("iv:                %s\n", 
	   octet_string_hex_string(iv, IV_LEN));
    printf("plaintext:         %s\n", 
	   octet_string_hex_string(opaque, *opaque_len));
#endif
    auth_tag = opaque;
    auth_tag += *opaque_len;
    for (i=0; i < NULL_TAG_LEN; i++)
      auth_tag[i] = i + (i * 16);
    *opaque_len += NULL_TAG_LEN;
#if DEBUG
    printf("protected data len: %d\n", *opaque_len);
    printf("protected data:    %s\n", 
	   octet_string_hex_string(opaque, *opaque_len));
#endif

  }

  return err_status_ok;
}
Example #6
0
void
ekt_write_data(ekt_stream_t ekt,
	       uint8_t *base_tag, 
	       unsigned base_tag_len, 
	       int *packet_len,
	       xtd_seq_num_t pkt_index) {
  uint32_t roc;
  uint16_t isn;
  unsigned emk_len;
  uint8_t *packet;

  /* if the pointer ekt is NULL, then EKT is not in effect */
  if (!ekt) {
    debug_print(mod_srtp, "EKT not in use", NULL);
    return;
  }

  /* write zeros into the location of the base tag */
  octet_string_set_to_zero(base_tag, base_tag_len);
  packet = base_tag + base_tag_len;

  /* copy encrypted master key into packet */
  emk_len = ekt_octets_after_base_tag(ekt);
  memcpy(packet, ekt->encrypted_master_key, emk_len);
  debug_print(mod_srtp, "writing EKT EMK: %s,", 
	      octet_string_hex_string(packet, emk_len));
  packet += emk_len;

  /* copy ROC into packet */
  roc = (uint32_t)(pkt_index >> 16);
  *((uint32_t *)packet) = be32_to_cpu(roc);
  debug_print(mod_srtp, "writing EKT ROC: %s,", 
	      octet_string_hex_string(packet, sizeof(roc)));
  packet += sizeof(roc);

  /* copy ISN into packet */
  isn = (uint16_t)pkt_index;
  *((uint16_t *)packet) = htons(isn);
  debug_print(mod_srtp, "writing EKT ISN: %s,", 
	      octet_string_hex_string(packet, sizeof(isn)));
  packet += sizeof(isn);

  /* copy SPI into packet */
  *((uint16_t *)packet) = htons(ekt->data->spi);
  debug_print(mod_srtp, "writing EKT SPI: %s,", 
	      octet_string_hex_string(packet, sizeof(ekt->data->spi)));

  /* increase packet length appropriately */
  *packet_len += EKT_OCTETS_AFTER_EMK + emk_len;
}
Example #7
0
err_status_t
hmac_init(hmac_ctx_t *state, const octet_t *key, int key_len) {
  int i;

  /*
   * check key length - note that we don't support keys larger
   * than 20 bytes yet
   */
  if (key_len > 20)              
    return err_status_bad_param;
  
  /*
   * set values of ipad and opad in the context by exoring the key
   * into the appropriate constant values
   */
  for (i=0; i < key_len; i++) {    
    state->ipad[i] = key[i] ^ 0x36;
    state->opad[i] = key[i] ^ 0x5c;
  }  
  /* set the rest of ipad, opad to constant values */
  for (   ; i < 64; i++) {    
    ((octet_t *)state->ipad)[i] = 0x36;
    ((octet_t *)state->opad)[i] = 0x5c;
  }  

  debug_print(mod_hmac, "ipad: %s", octet_string_hex_string(state->ipad, 64));
  
  /* initialize sha1 context */
  sha1_init(&state->ctx);

  /* hash ipad ^ key */
  sha1_update(&state->ctx, (octet_t *)state->ipad, 64);

  return err_status_ok;
}
char *
srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
    int octets_in_rtp_header = 12;
    uint8_t *data = ((uint8_t *) hdr) + octets_in_rtp_header;
    int hex_len = pkt_octet_len - octets_in_rtp_header;

    /* sanity checking */
    if ((hdr == NULL) || (pkt_octet_len > MTU))
        return NULL;

    /* write packet into string */
    sprintf(packet_string, "(s)rtp packet: {\n"
        "   version:\t%d\n"
        "   p:\t\t%d\n"
        "   x:\t\t%d\n"
        "   cc:\t\t%d\n"
        "   m:\t\t%d\n"
        "   pt:\t\t%x\n"
        "   seq:\t\t%x\n"
        "   ts:\t\t%x\n"
        "   ssrc:\t%x\n"
        "   data:\t%s\n"
        "} (%d octets in total)\n", hdr->version, hdr->p, hdr->x, hdr->cc,
            hdr->m, hdr->pt, hdr->seq, hdr->ts, hdr->ssrc,
            octet_string_hex_string(data, hex_len), pkt_octet_len);

    return packet_string;
}
Example #9
0
static void printSessionList (void) {
  ismacryp_session_t *temp;
  int i = 0;

  fprintf(stdout, "Session List:\n");

  if (sessionList == NULL) {
     fprintf(stdout, " -- EMPTY --\n");
     return;
  }

  temp=sessionList;
  while(temp != NULL) {
     i++;
     fprintf(stdout, " -- Session #%d: session id: %d \n", i, temp->sessid );
     fprintf(stdout, "                 key l: %d salt l: %d ctr l: %d iv l: %d key t: %c\n",
                                       AES_KEY_LEN, AES_SALT_LEN, AES_COUNTER_LEN, 
                                       temp->IV_len, 
                                       ismacryp_keytypeStr[temp->key_type][7]);
     fprintf(stdout, "                 key : %s", 
#ifdef HAVE_SRTP
                octet_string_hex_string(temp->kk.ksc.key, AES_KEY_LEN)
#else
                "n/a"
#endif
                );
     fprintf(stdout, "\n");
     fprintf(stdout, "                 salt: %s", 
#ifdef HAVE_SRTP
                octet_string_hex_string(temp->kk.ksc.salt, AES_SALT_LEN)
#else
                "n/a"
#endif
                );
     fprintf(stdout, "\n");
     fprintf(stdout, "                 ctr : %s", 
#ifdef HAVE_SRTP
                octet_string_hex_string(temp->kk.ksc.counter, AES_COUNTER_LEN)
#else
                "n/a"
#endif
                );
     fprintf(stdout, "\n");
     temp=temp->next;
  }

}
Example #10
0
err_status_t
null_dec(void *key,            
	 const void *clear,          
	 unsigned clear_len,       
	 void *iv,             
	 void *opaque,         
	 unsigned *opaque_len) {
  unsigned char *auth_tag;
  
  /* check if we're doing authentication only */
  if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
      
      /* perform authentication only */

  } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
    
    /*
     * bad parameter - we expect either all three pointers to be NULL,
     * or none of those pointers to be NULL 
     */
    return err_status_fail;

  } else {

#if DEBUG
    printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));

    printf("protected data len: %d\n", *opaque_len);
    printf("protected data:    %s\n", 
	   octet_string_hex_string(opaque, *opaque_len));
#endif
    auth_tag = opaque;
    auth_tag += (*opaque_len - NULL_TAG_LEN);
#if DEBUG
    printf("iv:         %s\n", octet_string_hex_string(iv, IV_LEN));
#endif
    *opaque_len -= NULL_TAG_LEN;
#if DEBUG
    printf("plaintext len:  %d\n", *opaque_len);
    printf("plaintext:  %s\n", 
	   octet_string_hex_string(opaque, *opaque_len));
#endif
  }

  return err_status_ok;
}
Example #11
0
err_status_t
hmac_compute (hmac_ctx_t *state, const void *message,
              int msg_octets, int tag_len, uint8_t *result)
{
    uint32_t hash_value[5];
    uint32_t H[5];
    int i;

    /* check tag length, return error if we can't provide the value expected */
    if (tag_len > HMAC_KEYLEN_MAX) {
        return err_status_bad_param;
    }

    /* hash message, copy output into H */
    sha1_update(&state->ctx, message, msg_octets);
    sha1_final(&state->ctx, H);

    /*
     * note that we don't need to debug_print() the input, since the
     * function hmac_update() already did that for us
     */
    debug_print(mod_hmac, "intermediate state: %s",
                octet_string_hex_string((uint8_t*)H, sizeof(H)));

    /* re-initialize hash context */
    sha1_init(&state->ctx);

    /* hash opad ^ key  */
    sha1_update(&state->ctx, (uint8_t*)state->opad, sizeof(state->opad));

    /* hash the result of the inner hash */
    sha1_update(&state->ctx, (uint8_t*)H, sizeof(H));

    /* the result is returned in the array hash_value[] */
    sha1_final(&state->ctx, hash_value);

    /* copy hash_value to *result */
    for (i = 0; i < tag_len; i++) {
        result[i] = ((uint8_t*)hash_value)[i];
    }

    debug_print(mod_hmac, "output: %s",
                octet_string_hex_string((uint8_t*)hash_value, tag_len));

    return err_status_ok;
}
Example #12
0
void
test_hex_string_funcs(void) {
  char hex1[] = "abadcafe";
  char hex2[] = "0123456789abcdefqqqqq";
  char raw[10];
  int len;

  len = hex_string_to_octet_string(raw, hex1, strlen(hex1));
  printf("computed length: %d\tstring: %s\n", len,
	 octet_string_hex_string(raw, len/2));
  printf("expected length: %u\tstring: %s\n", (unsigned)strlen(hex1), hex1);

  len = hex_string_to_octet_string(raw, hex2, strlen(hex2));
  printf("computed length: %d\tstring: %s\n", len,
	 octet_string_hex_string(raw, len/2));
  printf("expected length: %d\tstring: %s\n", 16, "0123456789abcdef");

}
// int main(int argc, char *argv[]) {
int aes_calc(char *key8, char *phrase8, char *cipher8) {
    v128_t data, key;
    aes_expanded_key_t exp_key;
    int len;
    int verbose = 0;

    /* read in key, checking length */
    if (strlen(key8) > AES_KEY_LEN * 2) {
        fprintf(stderr, "error: too many digits in key "
            "(should be %d hexadecimal digits, found %u)\n", AES_KEY_LEN * 2,
                (unsigned) strlen(key8));
        return(1);
    }
    len = hex_string_to_octet_string((char *) &key, key8, AES_KEY_LEN*2);
    /* check that hex string is the right length */
    if (len < AES_KEY_LEN * 2) {
        fprintf(stderr, "error: too few digits in key "
            "(should be %d hexadecimal digits, found %d)\n", AES_KEY_LEN * 2,
                len);
        return(1);
    }

    /* read in plaintext, checking length */
    if (strlen(phrase8) > 16 * 2) {
        fprintf(stderr, "error: too many digits in plaintext "
            "(should be %d hexadecimal digits, found %u)\n", 16 * 2,
                (unsigned) strlen(phrase8));
        return(1);
    }
    len = hex_string_to_octet_string((char *) (&data), phrase8, 16 * 2);
    /* check that hex string is the right length */
    if (len < 16 * 2) {
        fprintf(stderr, "error: too few digits in plaintext "
            "(should be %d hexadecimal digits, found %d)\n", 16 * 2, len);
        return(1);
    }

    if (verbose) {
        /* print out plaintext */
        printf("plaintext:\t%s\n", octet_string_hex_string((uint8_t *) &data,
                16));
    }

    /* encrypt plaintext */
    aes_expand_encryption_key(&key, exp_key);

    aes_encrypt(&data, exp_key);

    /* write ciphertext to output */
    if (verbose) {
        printf("key:\t\t%s\n", v128_hex_string(&key));
        printf("ciphertext:\t");
    }
    printf("%s\n", v128_hex_string(&data));

    return strcmp(v128_hex_string(&data), cipher8);
}
Example #14
0
void
test_bswap(void) {
  uint32_t x = 0x11223344;
  uint64_t y = 0x1122334455667788LL;

  printf("before: %0x\nafter:  %0x\n", x, (unsigned int)be32_to_cpu(x));
  printf("before: %0llx\nafter:  %0llx\n", (unsigned long long)y,
	 (unsigned long long)be64_to_cpu(y));

  y = 1234;

  printf("1234: %0llx\n", (unsigned long long)y);
  printf("as octet string: %s\n", 
	 octet_string_hex_string((uint8_t *) &y, 8));
  y = be64_to_cpu(y);
  printf("bswapped octet string: %s\n", 
	 octet_string_hex_string((uint8_t *) &y, 8));
}
Example #15
0
srtpw_err_status_t srtpw_srtp_protect(srtpw_srtp_policy *p, srtpw_srtp *srtp, void *buf, int *len,int rtcp)
{
    int res;
#ifdef DEBUG
    srtpw_log(err_level_debug,"reference packet before protection:\n%s",          
                      octet_string_hex_string((uint8_t *)buf, *len));
#endif
    return (res = rtcp ? srtp_protect_rtcp((srtp_t)srtp, buf, len) : srtp_protect((srtp_t)srtp, buf, len));
   
}
Example #16
0
File: hmac.c Project: dozeo/libsrtp
err_status_t
hmac_update(hmac_ctx_t *state, const uint8_t *message, int msg_octets) {

  debug_print(mod_hmac, "input: %s", 
	      octet_string_hex_string(message, msg_octets));
  
  /* hash message into sha1 context */
  sha1_update(&state->ctx, message, msg_octets);

  return err_status_ok;
}
err_status_t
aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len) {

    debug_print(mod_aes_cbc,
                "key:  %s", octet_string_hex_string(key, key_len));

    /*
     * Save the key until we have the IV later.  We don't
     * know the direction until the IV is set.
     */
    c->key_len = (key_len <= 32 ? key_len : 32);
    memcpy(c->key, key, c->key_len);

    return err_status_ok;
}
// int main(int argc, char *argv[]) {
int rand_gen(unsigned num_octets, unsigned do_debug) {
    unsigned do_list_mods = 0;
    err_status_t status;

    /* initialize kernel - we need to do this before anything else */
    status = crypto_kernel_init(0);
    if (status) {
        printf("error: crypto_kernel init failed\n");
        return(1);
    }

    if (do_debug) {
            status = crypto_kernel_set_debug_module(optarg, 1);
            if (status) {
                printf("error: set debug module (%s) failed\n", optarg);
                return(1);
            }
    }

    if (do_list_mods) {
        status = crypto_kernel_list_debug_modules();
        if (status) {
            printf("error: list of debug modules failed\n");
            return(1);
        }
    }

    if (num_octets > 0) {
        uint8_t buffer[BUF_LEN];

        status = crypto_get_random(buffer, num_octets);
        if (status) {
            printf("error: failure in random source\n");
        } else {
            printf("%s\n", octet_string_hex_string(buffer, num_octets));
        }
    }

    status = crypto_kernel_shutdown();
    if (status) {
        printf("error: crypto_kernel shutdown failed\n");
        return(1);
    }

    return 0;
}
Example #19
0
err_status_t
hmac_init (hmac_ctx_t *state, const uint8_t *key, int key_len)
{
    int i;
    uint8_t ipad[64];

    /*
     * check key length - note that we don't support keys larger
     * than 20 bytes yet
     */
    if (key_len > HMAC_KEYLEN_MAX) {
        return err_status_bad_param;
    }

    /*
     * set values of ipad and opad by exoring the key into the
     * appropriate constant values
     */
    for (i = 0; i < key_len; i++) {
        ipad[i] = key[i] ^ 0x36;
        state->opad[i] = key[i] ^ 0x5c;
    }
    /* set the rest of ipad, opad to constant values */
    for (; i < sizeof(ipad); i++) {
        ipad[i] = 0x36;
        ((uint8_t*)state->opad)[i] = 0x5c;
    }

    debug_print(mod_hmac, "ipad: %s", octet_string_hex_string(ipad, sizeof(ipad)));

    /* initialize sha1 context */
    sha1_init(&state->init_ctx);
    state->init_ctx_initialized = 1;

    /* hash ipad ^ key */
    sha1_update(&state->init_ctx, ipad, sizeof(ipad));
    return (hmac_start(state));
}
Example #20
0
char *srtpw_octet_string_hex_string(const void *str, int length) 
{
    return octet_string_hex_string(str,length);
}
Example #21
0
err_status_t
stat_test_rand_source(rand_source_func_t get_rand_bytes) {
  int i;
  double poker;
  uint8_t *data, *data_end;
  uint16_t f[16] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  };
  uint8_t buffer[RAND_SRC_BUF_OCTETS];
  err_status_t status;
  int ones_count = 0;
  uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; 
  uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
  uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
  uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
  int state = 0;
  uint16_t mask;
  
  /* counters for monobit, poker, and runs tests are initialized above */

  /* main loop: fill buffer, update counters for stat tests */
  for (i=0; i < 2500; i+=RAND_SRC_BUF_OCTETS) {
    
    /* fill data buffer */
    status = get_rand_bytes(buffer, RAND_SRC_BUF_OCTETS);
    if (status) {
	  debug_print(mod_stat, "couldn't get rand bytes: %d",status);
      return status;
	}

#if 0
    debug_print(mod_stat, "%s", 
		octet_string_hex_string(buffer, RAND_SRC_BUF_OCTETS));
#endif
  
    data = buffer;
    data_end = data + RAND_SRC_BUF_OCTETS;
    while (data < data_end) {

      /* update monobit test counter */
      ones_count += octet_get_weight(*data);

      /* update poker test counters */
      f[*data & 0x0f]++;    /* increment freq. count for low nibble  */
      f[(*data) >> 4]++;    /* increment freq. count for high nibble */

      /* update runs test counters */
      /* loop over the bits of this byte */
      for (mask = 1; mask < 256; mask <<= 1) {
	if (*data & mask) {
	  
	  /* next bit is a one  */
	  if (state > 0) {
	    
	    /* prefix is a run, so increment the run-count  */
	    state++;                          
	    
	    /* check for long runs */ 
	    if (state > 25) {
		  debug_print(mod_stat, ">25 runs (3): %d", state);
	      return err_status_algo_fail;
		}
	    
	  } else if (state < 0) {
	    
	    /* prefix is a gap  */
	    if (state < -25) {
		  debug_print(mod_stat, ">25 gaps (3): %d", state);
	      return err_status_algo_fail;    /* long-runs test failed   */
	    }
	    if (state < -6) {
	      state = -6;                     /* group together gaps > 5 */
	    }
	    gaps[-1-state]++;                 /* increment gap count      */
	    state = 1;                        /* set state at one set bit */
	  } else {
	    
	    /* state is zero; this happens only at initialization        */
	    state = 1;            
	  }
	} else {
	  
	  /* next bit is a zero  */
	  if (state > 0) {
	    
	    /* prefix is a run */
	    if (state > 25) {
		  debug_print(mod_stat, ">25 runs (4): %d", state);
	      return err_status_algo_fail;    /* long-runs test failed   */
	    }
	    if (state > 6) {
	      state = 6;                      /* group together runs > 5 */
	    }
	    runs[state-1]++;                  /* increment run count       */
	    state = -1;                       /* set state at one zero bit */
	  } else if (state < 0) {
	    
	    /* prefix is a gap, so increment gap-count (decrement state) */
	    state--;
	    
	    /* check for long gaps */ 
	    if (state < -25) {
		  debug_print(mod_stat, ">25 gaps (4): %d", state);
	      return err_status_algo_fail;
		}
	    
	  } else {
	    
	    /* state is zero; this happens only at initialization        */
	    state = -1;
	  }
	}
      }
      
      /* advance data pointer */
      data++;
    }
  }

  /* check to see if test data is within bounds */

  /* check monobit test data */

  debug_print(mod_stat, "stat: bit count: %d", ones_count);
  
  if ((ones_count < 9725) || (ones_count > 10275)) {
    debug_print(mod_stat, "stat: failed monobit test %d", ones_count);
    return err_status_algo_fail;
  }
  
  /* check poker test data */
  poker = 0.0;
  for (i=0; i < 16; i++) 
    poker += (double) f[i] * f[i];

  poker *= (16.0 / 5000.0);
  poker -= 5000.0;

  debug_print(mod_stat, "stat: poker test: %f", poker);
    
  if ((poker < 2.16) || (poker > 46.17)) {
    debug_print(mod_stat, "stat: failed poker test", NULL);
    return err_status_algo_fail;
  }

  /* check run and gap counts against the fixed limits */
  for (i=0; i < 6; i++) 
    if ((runs[i] < lo_value[i] ) || (runs[i] > hi_value[i])
	 || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) {
      debug_print(mod_stat, "stat: failed run/gap test", NULL);
      return err_status_algo_fail; 
    }

  debug_print(mod_stat, "passed random stat test", NULL);
  return err_status_ok;
}
Example #22
0
err_status_t
aes_128_cbc_hmac_sha1_96_enc(void *key,            
			     const void *clear,          
			     unsigned clear_len,       
			     void *iv,             
			     void *opaque,         
			     unsigned *opaque_len) {
  aes_cbc_ctx_t aes_ctx;
  hmac_ctx_t hmac_ctx;
  unsigned char enc_key[ENC_KEY_LEN];
  unsigned char mac_key[MAC_KEY_LEN];
  unsigned char *auth_tag;
  err_status_t status;

  /* check if we're doing authentication only */
  if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
      
      /* perform authentication only */

  } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
    
    /*
     * bad parameter - we expect either all three pointers to be NULL,
     * or none of those pointers to be NULL 
     */
    return err_status_fail;

  } else {

#if DEBUG
    printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
#endif

    /* derive encryption and authentication keys from the input key */
    status = hmac_init(&hmac_ctx, key, KEY_LEN);
    if (status) return status;
    status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
    if (status) return status;

    status = hmac_init(&hmac_ctx, key, KEY_LEN);
    if (status) return status;
    status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
    if (status) return status;


    /* perform encryption and authentication */

    /* set aes key */
    status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt);
    if (status) return status;

    /* set iv */
    status = rand_source_get_octet_string(iv, IV_LEN);  
    if (status) return status; 
    status = aes_cbc_set_iv(&aes_ctx, iv);
    if (status) return status;

#if DEBUG
    printf("plaintext len:  %d\n", *opaque_len);
    printf("iv:         %s\n", octet_string_hex_string(iv, IV_LEN));
    printf("plaintext:  %s\n", octet_string_hex_string(opaque, *opaque_len));
#endif

#if ENC    
    /* encrypt the opaque data  */
    status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
    if (status) return status;
#endif

#if DEBUG
    printf("ciphertext len: %d\n", *opaque_len);
    printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
#endif

    /*
     * authenticate clear and opaque data, then write the
     * authentication tag to the location immediately following the
     * ciphertext
     */
    status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
    if (status) return status;

    status = hmac_start(&hmac_ctx);
    if (status) return status;

    status = hmac_update(&hmac_ctx, clear, clear_len);
    if (status) return status;
#if DEBUG
    printf("hmac input: %s\n", 
	   octet_string_hex_string(clear, clear_len));
#endif
    auth_tag = (unsigned char *)opaque;
    auth_tag += *opaque_len;    
    status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
    if (status) return status;
#if DEBUG
    printf("hmac input: %s\n", 
	   octet_string_hex_string(opaque, *opaque_len));
#endif
    /* bump up the opaque_len to reflect the authentication tag */
    *opaque_len += TAG_LEN;

#if DEBUG
    printf("prot data len:  %d\n", *opaque_len);
    printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
#endif
  }

  return err_status_ok;
}
Example #23
0
err_status_t
auth_type_self_test(const auth_type_t *at) {
  auth_test_case_t *test_case = at->test_data;
  auth_t *a;
  err_status_t status;
  uint8_t tag[SELF_TEST_TAG_BUF_OCTETS];
  int i, case_num = 0;

  debug_print(mod_auth, "running self-test for auth function %s", 
	      at->description);
  
  /*
   * check to make sure that we have at least one test case, and
   * return an error if we don't - we need to be paranoid here
   */
  if (test_case == NULL)
    return err_status_cant_check;

  /* loop over all test cases */  
  while (test_case != NULL) {

    /* check test case parameters */
    if (test_case->tag_length_octets > SELF_TEST_TAG_BUF_OCTETS)
      return err_status_bad_param;
    
    /* allocate auth */
    status = auth_type_alloc(at, &a, test_case->key_length_octets,
			     test_case->tag_length_octets);
    if (status)
      return status;
    
    /* initialize auth */
    status = auth_init(a, test_case->key);
    if (status) {
      auth_dealloc(a);
      return status;
    }

    /* zeroize tag then compute */
    octet_string_set_to_zero(tag, test_case->tag_length_octets);
    status = auth_compute(a, test_case->data,
			  test_case->data_length_octets, tag);
    if (status) {
      auth_dealloc(a);
      return status;
    }
    
    debug_print(mod_auth, "key: %s",
		octet_string_hex_string(test_case->key,
					test_case->key_length_octets));
    debug_print(mod_auth, "data: %s",
		octet_string_hex_string(test_case->data,
				   test_case->data_length_octets));
    debug_print(mod_auth, "tag computed: %s",
	   octet_string_hex_string(tag, test_case->tag_length_octets));
    debug_print(mod_auth, "tag expected: %s",
	   octet_string_hex_string(test_case->tag,
				   test_case->tag_length_octets));

    /* check the result */
    status = err_status_ok;
    for (i=0; i < test_case->tag_length_octets; i++)
      if (tag[i] != test_case->tag[i]) {
	status = err_status_algo_fail;
	debug_print(mod_auth, "test case %d failed", case_num);
	debug_print(mod_auth, "  (mismatch at octet %d)", i);
      }
    if (status) {
      auth_dealloc(a);
      return err_status_algo_fail;
    }
    
    /* deallocate the auth function */
    status = auth_dealloc(a);
    if (status)
      return status;
    
    /* 
     * the auth function passed the test case, so move on to the next test
     * case in the list; if NULL, we'll quit and return an OK
     */   
    test_case = test_case->next_test_case;
    ++case_num;
  }
  
  return err_status_ok;
}
Example #24
0
int
main (int argc, char *argv[]) {
  char *dictfile = DICT_FILE;
  FILE *dict;
  char word[MAX_WORD_LEN];
  int sock, ret;
  struct in_addr rcvr_addr;
  struct sockaddr_in name;
  struct ip_mreq mreq;
#if BEW
  struct sockaddr_in local;
#endif 
  program_type prog_type = unknown;
  sec_serv_t sec_servs = sec_serv_none;
  unsigned char ttl = 5;
  int c;
  int key_size = 128;
  int tag_size = 8;
  int gcm_on = 0;
  char *input_key = NULL;
  char *address = NULL;
  char key[MAX_KEY_LEN];
  unsigned short port = 0;
  rtp_sender_t snd;
  srtp_policy_t policy;
  err_status_t status;
  int len;
  int do_list_mods = 0;
  uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
#ifdef RTPW_USE_WINSOCK2
  WORD wVersionRequested = MAKEWORD(2, 0);
  WSADATA wsaData;

  ret = WSAStartup(wVersionRequested, &wsaData);
  if (ret != 0) {
    fprintf(stderr, "error: WSAStartup() failed: %d\n", ret);
    exit(1);
  }
#endif

  if (setup_signal_handler(argv[0]) != 0) {
    exit(1);
  }

  /* initialize srtp library */
  status = srtp_init();
  if (status) {
    printf("error: srtp initialization failed with error code %d\n", status);
    exit(1);
  }

  /* check args */
  while (1) {
    c = getopt_s(argc, argv, "k:rsgt:ae:ld:");
    if (c == -1) {
      break;
    }
    switch (c) {
    case 'k':
      input_key = optarg_s;
      break;
    case 'e':
      key_size = atoi(optarg_s);
      if (key_size != 128 && key_size != 256) {
        printf("error: encryption key size must be 128 or 256 (%d)\n", key_size);
        exit(1);
      }
      sec_servs |= sec_serv_conf;
      break;
    case 't':
      tag_size = atoi(optarg_s);
      if (tag_size != 8 && tag_size != 16) {
        printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size);
        exit(1);
      }
      break;
    case 'a':
      sec_servs |= sec_serv_auth;
      break;
    case 'g':
      gcm_on = 1;
      sec_servs |= sec_serv_auth;
      break;
    case 'r':
      prog_type = receiver;
      break;
    case 's':
      prog_type = sender;
      break;
    case 'd':
      status = crypto_kernel_set_debug_module(optarg_s, 1);
      if (status) {
        printf("error: set debug module (%s) failed\n", optarg_s);
        exit(1);
      }
      break;
    case 'l':
      do_list_mods = 1;
      break;
    default:
      usage(argv[0]);
    }
  }

  if (prog_type == unknown) {
    if (do_list_mods) {
      status = crypto_kernel_list_debug_modules();
      if (status) {
	printf("error: list of debug modules failed\n");
	exit(1);
      }
      return 0;
    } else {
      printf("error: neither sender [-s] nor receiver [-r] specified\n");
      usage(argv[0]);
    }
  }
   
  if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
    /* 
     * a key must be provided if and only if security services have
     * been requested 
     */
    usage(argv[0]);
  }
    
  if (argc != optind_s + 2) {
    /* wrong number of arguments */
    usage(argv[0]);
  }

  /* get address from arg */
  address = argv[optind_s++];

  /* get port from arg */
  port = atoi(argv[optind_s++]);

  /* set address */
#ifdef HAVE_INET_ATON
  if (0 == inet_aton(address, &rcvr_addr)) {
    fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address);
    exit(1);
  }
  if (rcvr_addr.s_addr == INADDR_NONE) {
    fprintf(stderr, "%s: address error", argv[0]);
    exit(1);
  }
#else
  rcvr_addr.s_addr = inet_addr(address);
  if (0xffffffff == rcvr_addr.s_addr) {
    fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0], address);
    exit(1);
  }
#endif

  /* open socket */
  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (sock < 0) {
    int err;
#ifdef RTPW_USE_WINSOCK2
    err = WSAGetLastError();
#else
    err = errno;
#endif
    fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
   exit(1);
  }

  name.sin_addr   = rcvr_addr;    
  name.sin_family = PF_INET;
  name.sin_port   = htons(port);
 
  if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
    if (prog_type == sender) {
      ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 
  	               sizeof(ttl));
      if (ret < 0) {
	fprintf(stderr, "%s: Failed to set TTL for multicast group", argv[0]);
	perror("");
	exit(1);
      }
    }

    mreq.imr_multiaddr.s_addr = rcvr_addr.s_addr;
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&mreq,
		     sizeof(mreq));
    if (ret < 0) {
      fprintf(stderr, "%s: Failed to join multicast group", argv[0]);
      perror("");
      exit(1);
    }
  }

  /* report security services selected on the command line */
  printf("security services: ");
  if (sec_servs & sec_serv_conf)
    printf("confidentiality ");
  if (sec_servs & sec_serv_auth)
    printf("message authentication");
  if (sec_servs == sec_serv_none)
    printf("none");
  printf("\n");
  
  /* set up the srtp policy and master key */    
  if (sec_servs) {
    /* 
     * create policy structure, using the default mechanisms but 
     * with only the security services requested on the command line,
     * using the right SSRC value
     */
    switch (sec_servs) {
    case sec_serv_conf_and_auth:
      if (gcm_on) {
#ifdef OPENSSL
	switch (key_size) {
	case 128:
	  crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
	  crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
	  break;
	case 256:
	  crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
	  crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
	  break;
	}
#else
	printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n");
	return 0;
#endif
      } else {
	switch (key_size) {
	case 128:
          crypto_policy_set_rtp_default(&policy.rtp);
          crypto_policy_set_rtcp_default(&policy.rtcp);
	  break;
	case 256:
          crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
          crypto_policy_set_rtcp_default(&policy.rtcp);
	  break;
	}
      }
      break;
    case sec_serv_conf:
      if (gcm_on) {
	  printf("error: GCM mode must always be used with auth enabled\n");
	  return -1;
      } else {
	switch (key_size) {
	case 128:
          crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
          crypto_policy_set_rtcp_default(&policy.rtcp);      
	  break;
	case 256:
          crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
          crypto_policy_set_rtcp_default(&policy.rtcp);      
	  break;
	}
      }
      break;
    case sec_serv_auth:
      if (gcm_on) {
#ifdef OPENSSL
	switch (key_size) {
	case 128:
	  crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
	  crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp);
	  break;
	case 256:
	  crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
	  crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp);
	  break;
	}
#else
	printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n");
	return 0;
#endif
      } else {
        crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
        crypto_policy_set_rtcp_default(&policy.rtcp);
      }
      break;
    default:
      printf("error: unknown security service requested\n");
      return -1;
    } 
    policy.ssrc.type  = ssrc_specific;
    policy.ssrc.value = ssrc;
    policy.key  = (uint8_t *) key;
    policy.ekt  = NULL;
    policy.next = NULL;
    policy.window_size = 128;
    policy.allow_repeat_tx = 0;
    policy.rtp.sec_serv = sec_servs;
    policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */

    if (gcm_on && tag_size != 8) {
	policy.rtp.auth_tag_len = tag_size;
    }

    /*
     * read key from hexadecimal on command line into an octet string
     */
    len = hex_string_to_octet_string(key, input_key, policy.rtp.cipher_key_len*2);
    
    /* check that hex string is the right length */
    if (len < policy.rtp.cipher_key_len*2) {
      fprintf(stderr, 
	      "error: too few digits in key/salt "
	      "(should be %d hexadecimal digits, found %d)\n",
	      policy.rtp.cipher_key_len*2, len);
      exit(1);    
    } 
    if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
      fprintf(stderr, 
	      "error: too many digits in key/salt "
	      "(should be %d hexadecimal digits, found %u)\n",
	      policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key));
      exit(1);    
    }
    
    printf("set master key/salt to %s/", octet_string_hex_string(key, 16));
    printf("%s\n", octet_string_hex_string(key+16, 14));
  
  } else {
    /*
     * we're not providing security services, so set the policy to the
     * null policy
     *
     * Note that this policy does not conform to the SRTP
     * specification, since RTCP authentication is required.  However,
     * the effect of this policy is to turn off SRTP, so that this
     * application is now a vanilla-flavored RTP application.
     */
    policy.key                 = (uint8_t *)key;
    policy.ssrc.type           = ssrc_specific;
    policy.ssrc.value          = ssrc;
    policy.rtp.cipher_type     = NULL_CIPHER;
    policy.rtp.cipher_key_len  = 0; 
    policy.rtp.auth_type       = NULL_AUTH;
    policy.rtp.auth_key_len    = 0;
    policy.rtp.auth_tag_len    = 0;
    policy.rtp.sec_serv        = sec_serv_none;   
    policy.rtcp.cipher_type    = NULL_CIPHER;
    policy.rtcp.cipher_key_len = 0; 
    policy.rtcp.auth_type      = NULL_AUTH;
    policy.rtcp.auth_key_len   = 0;
    policy.rtcp.auth_tag_len   = 0;
    policy.rtcp.sec_serv       = sec_serv_none;   
    policy.window_size         = 0;
    policy.allow_repeat_tx     = 0;
    policy.ekt                 = NULL;
    policy.next                = NULL;
  }

  if (prog_type == sender) {

#if BEW
    /* bind to local socket (to match crypto policy, if need be) */
    memset(&local, 0, sizeof(struct sockaddr_in));
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    local.sin_port = htons(port);
    ret = bind(sock, (struct sockaddr *) &local, sizeof(struct sockaddr_in));
    if (ret < 0) {
      fprintf(stderr, "%s: bind failed\n", argv[0]);
      perror("");
      exit(1); 
    }
#endif /* BEW */

    /* initialize sender's rtp and srtp contexts */
    snd = rtp_sender_alloc();
    if (snd == NULL) {
      fprintf(stderr, "error: malloc() failed\n");
      exit(1);
    }
    rtp_sender_init(snd, sock, name, ssrc); 
    status = rtp_sender_init_srtp(snd, &policy);
    if (status) {
      fprintf(stderr, 
	      "error: srtp_create() failed with code %d\n", 
	      status);
      exit(1);
    }
 
    /* open dictionary */
    dict = fopen (dictfile, "r");
    if (dict == NULL) {
      fprintf(stderr, "%s: couldn't open file %s\n", argv[0], dictfile);
      if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
  	leave_group(sock, mreq, argv[0]);
      }
      exit(1);
    }
          
    /* read words from dictionary, then send them off */
    while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) { 
      len = strlen(word) + 1;  /* plus one for null */
      
      if (len > MAX_WORD_LEN) 
	printf("error: word %s too large to send\n", word);
      else {
	rtp_sendto(snd, word, len);
        printf("sending word: %s", word);
      }
      usleep(USEC_RATE);
    }

    rtp_sender_deinit_srtp(snd);
    rtp_sender_dealloc(snd);

    fclose(dict);
  } else  { /* prog_type == receiver */
    rtp_receiver_t rcvr;
        
    if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
      close(sock);
      fprintf(stderr, "%s: socket bind error\n", argv[0]);
      perror(NULL);
      if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
    	leave_group(sock, mreq, argv[0]);
      }
      exit(1);
    }

    rcvr = rtp_receiver_alloc();
    if (rcvr == NULL) {
      fprintf(stderr, "error: malloc() failed\n");
      exit(1);
    }
    rtp_receiver_init(rcvr, sock, name, ssrc);
    status = rtp_receiver_init_srtp(rcvr, &policy);
    if (status) {
      fprintf(stderr, 
	      "error: srtp_create() failed with code %d\n", 
	      status);
      exit(1);
    }

    /* get next word and loop */
    while (!interrupted) {
      len = MAX_WORD_LEN;
      if (rtp_recvfrom(rcvr, word, &len) > -1)
	printf("\tword: %s\n", word);
    }
      
    rtp_receiver_deinit_srtp(rcvr);
    rtp_receiver_dealloc(rcvr);
  } 

  if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
    leave_group(sock, mreq, argv[0]);
  }

#ifdef RTPW_USE_WINSOCK2
  ret = closesocket(sock);
#else
  ret = close(sock);
#endif
  if (ret < 0) {
    fprintf(stderr, "%s: Failed to close socket", argv[0]);
    perror("");
  }

  status = srtp_shutdown();
  if (status) {
    printf("error: srtp shutdown failed with error code %d\n", status);
    exit(1);
  }

#ifdef RTPW_USE_WINSOCK2
  WSACleanup();
#endif

  return 0;
}
Example #25
0
err_status_t
aes_128_cbc_hmac_sha1_96_dec(void *key,            
			     const void *clear,          
			     unsigned clear_len,       
			     void *iv,             
			     void *opaque,         
			     unsigned *opaque_len) {
  aes_cbc_ctx_t aes_ctx;
  hmac_ctx_t hmac_ctx;
  unsigned char enc_key[ENC_KEY_LEN];
  unsigned char mac_key[MAC_KEY_LEN];
  unsigned char tmp_tag[TAG_LEN];
  unsigned char *auth_tag;
  unsigned ciphertext_len;
  err_status_t status;
  int i;
  
  /* check if we're doing authentication only */
  if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
      
      /* perform authentication only */

  } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
    
    /*
     * bad parameter - we expect either all three pointers to be NULL,
     * or none of those pointers to be NULL 
     */
    return err_status_fail;

  } else {
#if DEBUG
    printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
#endif

    /* derive encryption and authentication keys from the input key */
    status = hmac_init(&hmac_ctx, key, KEY_LEN);
    if (status) return status;
    status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
    if (status) return status;

    status = hmac_init(&hmac_ctx, key, KEY_LEN);
    if (status) return status;
    status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
    if (status) return status;

#if DEBUG
    printf("prot data len:  %d\n", *opaque_len);
    printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
#endif

    /* 
     * set the protected data length to that of the ciphertext, by
     * subtracting out the length of the authentication tag 
     */
    ciphertext_len = *opaque_len - TAG_LEN;

#if DEBUG
    printf("ciphertext len: %d\n", ciphertext_len);
#endif    
    /* verify the authentication tag */

    /* 
     * compute the authentication tag for the clear and opaque data,
     * and write it to a temporary location
     */
    status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
    if (status) return status;

    status = hmac_start(&hmac_ctx);
    if (status) return status;

    status = hmac_update(&hmac_ctx, clear, clear_len);
    if (status) return status;

#if DEBUG
    printf("hmac input: %s\n", 
	   octet_string_hex_string(clear, clear_len));
#endif

    status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag);
    if (status) return status;

#if DEBUG
    printf("hmac input: %s\n", 
	   octet_string_hex_string(opaque, ciphertext_len));
#endif

    /* 
     * compare the computed tag with the one provided as input (which
     * immediately follows the ciphertext)
     */
    auth_tag = (unsigned char *)opaque;
    auth_tag += ciphertext_len;  
#if DEBUG
    printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN));
    printf("tmp_tag:  %s\n", octet_string_hex_string(tmp_tag, TAG_LEN));
#endif
    for (i=0; i < TAG_LEN; i++) {
      if (tmp_tag[i] != auth_tag[i]) 
	return err_status_auth_fail; 
    }

    /* bump down the opaque_len to reflect the authentication tag */
    *opaque_len -= TAG_LEN;

    /* decrypt the confidential data */
    status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt);
    if (status) return status;
    status = aes_cbc_set_iv(&aes_ctx, iv);
    if (status) return status;

#if DEBUG
    printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
    printf("iv:         %s\n", octet_string_hex_string(iv, IV_LEN));
#endif

#if ENC
    status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len);
    if (status) return status;
#endif

#if DEBUG
    printf("plaintext len:  %d\n", ciphertext_len);
    printf("plaintext:  %s\n", 
	   octet_string_hex_string(opaque, ciphertext_len));
#endif

    /* indicate the length of the plaintext  */
    *opaque_len = ciphertext_len;
  }

  return err_status_ok;
}
Example #26
0
/*
 * Initialize and start SRTP session with the given parameters.
 */
PJ_DEF(pj_status_t) pjmedia_transport_srtp_start(
			   pjmedia_transport *tp, 
			   const pjmedia_srtp_crypto *tx,
			   const pjmedia_srtp_crypto *rx)
{
    transport_srtp  *srtp = (transport_srtp*) tp;
    srtp_policy_t    tx_;
    srtp_policy_t    rx_;
    err_status_t     err;
    int		     cr_tx_idx = 0;
    int		     au_tx_idx = 0;
    int		     cr_rx_idx = 0;
    int		     au_rx_idx = 0;
    int		     crypto_suites_cnt;

    PJ_ASSERT_RETURN(tp && tx && rx, PJ_EINVAL);

    if (srtp->session_inited) {
	pjmedia_transport_srtp_stop(tp);
    }

    crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);

    /* Get encryption and authentication method */
    cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name);
    if (tx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
	cr_tx_idx = 0;
    if (tx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
	au_tx_idx = 0;

    cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name);
    if (rx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
	cr_rx_idx = 0;
    if (rx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
	au_rx_idx = 0;

    /* Check whether the crypto-suite requested is supported */
    if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || 
	au_rx_idx == -1)
	return PJMEDIA_SRTP_ENOTSUPCRYPTO;

    /* If all options points to 'NULL' method, just bypass SRTP */
    if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
	srtp->bypass_srtp = PJ_TRUE;
	return PJ_SUCCESS;
    }

    /* Check key length */
    if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len ||
        rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len)
	return PJMEDIA_SRTP_EINKEYLEN;

    /* Init transmit direction */
    pj_bzero(&tx_, sizeof(srtp_policy_t));
    pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen);
    if (cr_tx_idx && au_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_conf_and_auth;
    else if (cr_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_conf;
    else if (au_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_auth;
    else
	tx_.rtp.sec_serv    = sec_serv_none;
    tx_.key		    = (uint8_t*)srtp->tx_key;
    tx_.ssrc.type	    = ssrc_any_outbound;
    tx_.ssrc.value	    = 0;
    tx_.rtp.cipher_type	    = crypto_suites[cr_tx_idx].cipher_type;
    tx_.rtp.cipher_key_len  = crypto_suites[cr_tx_idx].cipher_key_len;
    tx_.rtp.auth_type	    = crypto_suites[au_tx_idx].auth_type;
    tx_.rtp.auth_key_len    = crypto_suites[au_tx_idx].auth_key_len;
    tx_.rtp.auth_tag_len    = crypto_suites[au_tx_idx].srtp_auth_tag_len;
    tx_.rtcp		    = tx_.rtp;
    tx_.rtcp.auth_tag_len   = crypto_suites[au_tx_idx].srtcp_auth_tag_len;
    tx_.next		    = NULL;
    err = srtp_create(&srtp->srtp_tx_ctx, &tx_);
    if (err != err_status_ok) {
	return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
    }
    srtp->tx_policy = *tx;
    pj_strset(&srtp->tx_policy.key,  srtp->tx_key, tx->key.slen);
    srtp->tx_policy.name=pj_str(crypto_suites[get_crypto_idx(&tx->name)].name);


    /* Init receive direction */
    pj_bzero(&rx_, sizeof(srtp_policy_t));
    pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen);
    if (cr_rx_idx && au_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_conf_and_auth;
    else if (cr_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_conf;
    else if (au_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_auth;
    else
	rx_.rtp.sec_serv    = sec_serv_none;
    rx_.key		    = (uint8_t*)srtp->rx_key;
    rx_.ssrc.type	    = ssrc_any_inbound;
    rx_.ssrc.value	    = 0;
    rx_.rtp.sec_serv	    = crypto_suites[cr_rx_idx].service;
    rx_.rtp.cipher_type	    = crypto_suites[cr_rx_idx].cipher_type;
    rx_.rtp.cipher_key_len  = crypto_suites[cr_rx_idx].cipher_key_len;
    rx_.rtp.auth_type	    = crypto_suites[au_rx_idx].auth_type;
    rx_.rtp.auth_key_len    = crypto_suites[au_rx_idx].auth_key_len;
    rx_.rtp.auth_tag_len    = crypto_suites[au_rx_idx].srtp_auth_tag_len;
    rx_.rtcp		    = rx_.rtp;
    rx_.rtcp.auth_tag_len   = crypto_suites[au_rx_idx].srtcp_auth_tag_len;
    rx_.next		    = NULL;
    err = srtp_create(&srtp->srtp_rx_ctx, &rx_);
    if (err != err_status_ok) {
	srtp_dealloc(srtp->srtp_tx_ctx);
	return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
    }
    srtp->rx_policy = *rx;
    pj_strset(&srtp->rx_policy.key,  srtp->rx_key, rx->key.slen);
    srtp->rx_policy.name=pj_str(crypto_suites[get_crypto_idx(&rx->name)].name);

    /* Declare SRTP session initialized */
    srtp->session_inited = PJ_TRUE;

    PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s", srtp->tx_policy.name.ptr,
	       octet_string_hex_string(tx->key.ptr, tx->key.slen)));
    if (srtp->tx_policy.flags) {
	PJ_LOG(5,(srtp->pool->obj_name,"TX: disable%s%s", (cr_tx_idx?"":" enc"),
		  (au_tx_idx?"":" auth")));
    }

    PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s", srtp->rx_policy.name.ptr,
	       octet_string_hex_string(rx->key.ptr, rx->key.slen)));
    if (srtp->rx_policy.flags) {
	PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s", (cr_rx_idx?"":" enc"),
		  (au_rx_idx?"":" auth")));
    }

    return PJ_SUCCESS;
}
Example #27
0
int main(int argc, char *argv[])
{
    int q;
    int num_octets = 0;
    err_status_t status;
    uint32_t iterations = 0;
    int print_values = 0;

    if (argc == 1) {
        exit(255);
    }

    status = crypto_kernel_init();
    if (status) {
        printf("error: crypto_kernel init failed\n");
        exit(1);
    }

    while (1) {
        q = getopt_s(argc, argv, "pvn:");
        if (q == -1) {
            break;
        }
        switch (q) {
        case 'p':
            print_values = 1;
            break;
        case 'n':
            num_octets = atoi(optarg_s);
            if (num_octets < 0 || num_octets > BUF_LEN) {
                exit(255);
            }
            break;
        case 'v':
            num_octets = 30;
            print_values = 0;
            break;
        default:
            exit(255);
        }
    }

    if (num_octets > 0) {
        while (iterations < 300000) {
            uint8_t buffer[BUF_LEN];

            status = crypto_get_random(buffer, num_octets);
            if (status) {
                printf("iteration %d error: failure in random source\n", iterations);
                exit(255);
            } else if (print_values) {
                printf("%s\n", octet_string_hex_string(buffer, num_octets));
            }
            iterations++;
        }
    }

    status = crypto_kernel_shutdown();
    if (status) {
        printf("error: crypto_kernel shutdown failed\n");
        exit(1);
    }

    return 0;
}
err_status_t
cipher_driver_test_buffering (cipher_t *c)
{
    int i, j, num_trials = 1000;
    unsigned len, buflen = 1024;
    uint8_t buffer0[buflen], buffer1[buflen], *current, *end;
    uint8_t idx[16] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34
    };
    err_status_t status;

    printf("testing output buffering for cipher %s...",
           c->type->description);

    for (i = 0; i < num_trials; i++) {

        /* set buffers to zero */
        for (j = 0; j < buflen; j++) {
            buffer0[j] = buffer1[j] = 0;
        }

        /* initialize cipher  */
        status = cipher_set_iv(c, idx, direction_encrypt);
        if (status) {
            return status;
        }

        /* generate 'reference' value by encrypting all at once */
        status = cipher_encrypt(c, buffer0, &buflen);
        if (status) {
            return status;
        }

        /* re-initialize cipher */
        status = cipher_set_iv(c, idx, direction_encrypt);
        if (status) {
            return status;
        }

        /* now loop over short lengths until buffer1 is encrypted */
        current = buffer1;
        end = buffer1 + buflen;
        while (current < end) {

            /* choose a short length */
            len = rand() & 0x01f;

            /* make sure that len doesn't cause us to overreach the buffer */
            if (current + len > end) {
                len = end - current;
            }

            status = cipher_encrypt(c, current, &len);
            if (status) {
                return status;
            }

            /* advance pointer into buffer1 to reflect encryption */
            current += len;

            /* if buffer1 is all encrypted, break out of loop */
            if (current == end) {
                break;
            }
        }

        /* compare buffers */
        for (j = 0; j < buflen; j++) {
            if (buffer0[j] != buffer1[j]) {
#if PRINT_DEBUG
                printf("test case %d failed at byte %d\n", i, j);
                printf("computed: %s\n", octet_string_hex_string(buffer1, buflen));
                printf("expected: %s\n", octet_string_hex_string(buffer0, buflen));
#endif
                return err_status_algo_fail;
            }
        }
    }

    printf("passed\n");

    return err_status_ok;
}
Example #29
0
err_status_t
srtcp_test(const srtp_policy_t *policy) {
  int i;
  srtp_t srtcp_sender;
  srtp_t srtcp_rcvr;
  err_status_t status = err_status_ok;
  srtp_hdr_t *hdr, *hdr2;
  uint8_t hdr_enc[64];
  uint8_t *pkt_end;
  int msg_len_octets, msg_len_enc;
  int len;
  int tag_length = policy->rtp.auth_tag_len; 
  uint32_t ssrc;
  srtp_policy_t *rcvr_policy;

  err_check(srtp_create(&srtcp_sender, policy));

  /* print out policy */
  err_check(srtp_session_print_policy(srtcp_sender)); 

  /*
   * initialize data buffer, using the ssrc in the policy unless that
   * value is a wildcard, in which case we'll just use an arbitrary
   * one
   */
  if (policy->ssrc.type != ssrc_specific)
    ssrc = 0xdecafbad;
  else
    ssrc = policy->ssrc.value;
  msg_len_octets = 28;
  hdr = srtp_create_test_packet(msg_len_octets, ssrc);

  if (hdr == NULL)
    return err_status_alloc_fail;
  hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
  if (hdr2 == NULL) {
    free(hdr);
    return err_status_alloc_fail;
  }

  /* set message length */
  len = msg_len_octets;

  debug_print(mod_driver, "before protection:\n%s", 	      
	      srtp_packet_to_string(hdr, len));

#if PRINT_REFERENCE_PACKET
  debug_print(mod_driver, "reference packet before protection:\n%s", 	      
	      octet_string_hex_string((uint8_t *)hdr, len));
#endif
  err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));

  debug_print(mod_driver, "after protection:\n%s", 	      
	      srtp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
  debug_print(mod_driver, "after protection:\n%s", 	      
	      octet_string_hex_string((uint8_t *)hdr, len));
#endif

  /* save protected message and length */
  memcpy(hdr_enc, hdr, len);
  msg_len_enc = len;

  /* 
   * check for overrun of the srtp_protect() function
   *
   * The packet is followed by a value of 0xfffff; if the value of the
   * data following the packet is different, then we know that the
   * protect function is overwriting the end of the packet.
   */
  pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t) 
    + msg_len_octets + tag_length;
  for (i = 0; i < 4; i++)
    if (pkt_end[i] != 0xff) {
      fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
              "(expected %x, found %x in trailing octet %d)\n",
              0xff, ((uint8_t *)hdr)[i], i);
      free(hdr);
      free(hdr2);
      return err_status_algo_fail;
    }  

  /*
   * if the policy includes confidentiality, check that ciphertext is
   * different than plaintext
   * 
   * Note that this check will give false negatives, with some small
   * probability, especially if the packets are short.  For that
   * reason, we skip this check if the plaintext is less than four
   * octets long.
   */
  if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
    printf("testing that ciphertext is distinct from plaintext...");
    status = err_status_algo_fail;
    for (i=12; i < msg_len_octets+12; i++)
      if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
	status = err_status_ok;
      }
    if (status) {
      printf("failed\n");
      free(hdr);
      free(hdr2);
      return status;
    }
    printf("passed\n");
  }
  
  /*
   * if the policy uses a 'wildcard' ssrc, then we need to make a copy
   * of the policy that changes the direction to inbound
   *
   * we always copy the policy into the rcvr_policy, since otherwise
   * the compiler would fret about the constness of the policy
   */
  rcvr_policy = malloc(sizeof(srtp_policy_t));
  if (rcvr_policy == NULL)
    return err_status_alloc_fail;
  memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
  if (policy->ssrc.type == ssrc_any_outbound) {
    rcvr_policy->ssrc.type = ssrc_any_inbound;       
  } 

  err_check(srtp_create(&srtcp_rcvr, rcvr_policy));
   
  err_check(srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len));

  debug_print(mod_driver, "after unprotection:\n%s", 	      
	      srtp_packet_to_string(hdr, len));

  /* verify that the unprotected packet matches the origial one */
  for (i=0; i < msg_len_octets; i++)
    if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
      fprintf(stdout, "mismatch at octet %d\n", i);
      status = err_status_algo_fail;
    }
  if (status) {
    free(hdr);
    free(hdr2);
    return status;
  }

  /* 
   * if the policy includes authentication, then test for false positives
   */  
  if (policy->rtp.sec_serv & sec_serv_auth) {
    char *data = ((char *)hdr) + 12;
    
    printf("testing for false positives in replay check...");

    /* set message length */
    len = msg_len_enc;

    /* unprotect a second time - should fail with a replay error */
    status = srtp_unprotect_rtcp(srtcp_rcvr, hdr_enc, &len);
    if (status != err_status_replay_fail) {
      printf("failed with error code %d\n", status);
      free(hdr); 
      free(hdr2);
      return status;
    } else {
      printf("passed\n");
    }

    printf("testing for false positives in auth check...");

    /* increment sequence number in header */
    hdr->seq++; 

    /* set message length */
    len = msg_len_octets;

    /* apply protection */
    err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
    
    /* flip bits in packet */
    data[0] ^= 0xff;

    /* unprotect, and check for authentication failure */
    status = srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len);
    if (status != err_status_auth_fail) {
      printf("failed\n");
      free(hdr); 
      free(hdr2);
      return status;
    } else {
      printf("passed\n");
    }
            
  }

  err_check(srtp_dealloc(srtcp_sender));
  err_check(srtp_dealloc(srtcp_rcvr));

  free(hdr);
  free(hdr2);
  return err_status_ok;
}
Example #30
0
int
main (int argc, char *argv[]) {
  extern char *optarg;
  int q;
  int num_octets = 0;
  unsigned do_list_mods = 0;
  err_status_t status;

  if (argc == 1)
    usage(argv[0]);

  /* initialize kernel - we need to do this before anything else */ 
  status = crypto_kernel_init();
  if (status) {
    printf("error: crypto_kernel init failed\n");
    exit(1);
  }

  /* process input arguments */
  while (1) {
    q = getopt(argc, argv, "ld:n:");
    if (q == -1) 
      break;
    switch (q) {
    case 'd':
      status = crypto_kernel_set_debug_module(optarg, 1);
      if (status) {
	printf("error: set debug module (%s) failed\n", optarg);
	exit(1);
      }
      break;
    case 'l':
      do_list_mods = 1;
      break;
    case 'n':
      num_octets = atoi(optarg);
      if (num_octets < 0 || num_octets > BUF_LEN)
	usage(argv[0]);
      break;
    default:
      usage(argv[0]);
    }    
  }

  if (do_list_mods) {
    status = crypto_kernel_list_debug_modules();
    if (status) {
      printf("error: list of debug modules failed\n");
      exit(1);
    }
  }

  if (num_octets > 0) {
    uint8_t buffer[BUF_LEN];
    
    status = crypto_get_random(buffer, num_octets);
    if (status) {
      printf("error: failure in random source\n");
    } else {
      printf("%s\n", octet_string_hex_string(buffer, num_octets));
    }
  }

  status = crypto_kernel_shutdown();
  if (status) {
    printf("error: crypto_kernel shutdown failed\n");
    exit(1);
  }
  
  return 0;
}