/* Generate a private/public keypair. */
OSStatus SecKeyGeneratePair(CFDictionaryRef parameters,
                            SecKeyRef *publicKey, SecKeyRef *privateKey) {
    OSStatus result = errSecUnsupportedAlgorithm;
    SecKeyRef privKey = NULL;
	SecKeyRef pubKey = NULL;
    CFMutableDictionaryRef pubParams = merge_params(parameters, kSecPublicKeyAttrs),
    privParams = merge_params(parameters, kSecPrivateKeyAttrs);
	CFStringRef ktype = CFDictionaryGetValue(parameters, kSecAttrKeyType);
    
    require(ktype, errOut);
    
    if (CFEqual(ktype, kSecAttrKeyTypeEC)) {
        result = SecECKeyGeneratePair(parameters, &pubKey, &privKey);
    } else if (CFEqual(ktype, kSecAttrKeyTypeRSA)) {
        result = SecRSAKeyGeneratePair(parameters, &pubKey, &privKey);
    }
    
    require_noerr(result, errOut);
    
    /* Store the keys in the keychain if they are marked as permanent. */
    if (getBoolForKey(pubParams, kSecAttrIsPermanent, false)) {
        require_noerr_quiet(result = add_ref(pubKey, pubParams), errOut);
    }
    if (getBoolForKey(privParams, kSecAttrIsPermanent, false)) {
        require_noerr_quiet(result = add_ref(privKey, privParams), errOut);
    }
    
    if (publicKey) {
        *publicKey = pubKey;
        pubKey = NULL;
    }
    if (privateKey) {
        *privateKey = privKey;
        privKey = NULL;
    }
    
errOut:
	CFReleaseSafe(pubParams);
	CFReleaseSafe(privParams);
    CFReleaseSafe(pubKey);
    CFReleaseSafe(privKey);
    
    return result;
}
static char *
sign_hmac (OAuthProxy *proxy, RestProxyCall *call, GHashTable *oauth_params)
{
  OAuthProxyPrivate *priv;
  RestProxyCallPrivate *callpriv;
  char *key, *signature, *ep, *eep;
  GString *text;
  GHashTable *all_params;

  priv = PROXY_GET_PRIVATE (proxy);
  callpriv = call->priv;

  text = g_string_new (NULL);
  g_string_append (text, rest_proxy_call_get_method (REST_PROXY_CALL (call)));
  g_string_append_c (text, '&');
  if (priv->oauth_echo) {
    g_string_append_uri_escaped (text, priv->service_url, NULL, FALSE);
  } else if (priv->signature_host != NULL) {
    SoupURI *url = soup_uri_new (callpriv->url);
    gchar *signing_url;

    soup_uri_set_host (url, priv->signature_host);
    signing_url = soup_uri_to_string (url, FALSE);

    g_string_append_uri_escaped (text, signing_url, NULL, FALSE);

    soup_uri_free (url);
    g_free (signing_url);
  } else {
    g_string_append_uri_escaped (text, callpriv->url, NULL, FALSE);
  }
  g_string_append_c (text, '&');

  /* Merge the OAuth parameters with the query parameters */
  all_params = g_hash_table_new (g_str_hash, g_str_equal);
  merge_hashes (all_params, oauth_params);
  if (!priv->oauth_echo)
    merge_params (all_params, callpriv->params);

  ep = encode_params (all_params);
  eep = OAUTH_ENCODE_STRING (ep);
  g_string_append (text, eep);
  g_free (ep);
  g_free (eep);
  g_hash_table_destroy (all_params);

  /* PLAINTEXT signature value is the HMAC-SHA1 key value */
  key = sign_plaintext (priv);

  signature = hmac_sha1 (key, text->str);

  g_free (key);
  g_string_free (text, TRUE);

  return signature;
}