/*
 * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

/*
  DTLS code by Eric Rescorla <ekr@rtfm.com>

  Copyright (C) 2006, Network Resonance, Inc.
  Copyright (C) 2011, RTFM, Inc.
*/

#include <openssl/ssl.h>

#include <string.h>

#include <openssl/bytestring.h>
#include <openssl/err.h>

#include "internal.h"


using namespace bssl;

static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
    {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80},
    {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32},
    {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM},
    {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM},
    {0, 0},
};

static int find_profile_by_name(const char *profile_name,
                                const SRTP_PROTECTION_PROFILE **pptr,
                                size_t len) {
  const SRTP_PROTECTION_PROFILE *p = kSRTPProfiles;
  while (p->name) {
    if (len == strlen(p->name) && !strncmp(p->name, profile_name, len)) {
      *pptr = p;
      return 1;
    }

    p++;
  }

  return 0;
}

static int ssl_ctx_make_profiles(
    const char *profiles_string,
    UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> *out) {
  UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> profiles(
      sk_SRTP_PROTECTION_PROFILE_new_null());
  if (profiles == nullptr) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
    return 0;
  }

  const char *col;
  const char *ptr = profiles_string;
  do {
    col = strchr(ptr, ':');

    const SRTP_PROTECTION_PROFILE *profile;
    if (!find_profile_by_name(ptr, &profile,
                              col ? (size_t)(col - ptr) : strlen(ptr))) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
      return 0;
    }

    if (!sk_SRTP_PROTECTION_PROFILE_push(profiles.get(), profile)) {
      return 0;
    }

    if (col) {
      ptr = col + 1;
    }
  } while (col);

  *out = std::move(profiles);
  return 1;
}

int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx, const char *profiles) {
  return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles);
}

int SSL_set_srtp_profiles(SSL *ssl, const char *profiles) {
  return ssl->config != nullptr &&
         ssl_ctx_make_profiles(profiles, &ssl->config->srtp_profiles);
}

const STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(const SSL *ssl) {
  if (ssl == nullptr) {
    return nullptr;
  }

  if (ssl->config == nullptr) {
    assert(0);
    return nullptr;
  }

  return ssl->config->srtp_profiles != nullptr
             ? ssl->config->srtp_profiles.get()
             : ssl->ctx->srtp_profiles.get();
}

const SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *ssl) {
  return ssl->s3->srtp_profile;
}

int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) {
  // This API inverts its return value.
  return !SSL_CTX_set_srtp_profiles(ctx, profiles);
}

int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles) {
  // This API inverts its return value.
  return !SSL_set_srtp_profiles(ssl, profiles);
}
