/* sign-macos.c
 *
 * Copyright (c) 2018-2021 Apple Computer, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * DNS SIG(0) signature generation for DNSSD SRP using mbedtls.
 *
 * Functions required for loading, saving, and generating public/private keypairs, extracting the public key
 * into KEY RR data, and computing signatures.
 *
 * This is the implementation for Mac OS X.
 */


#include <stdio.h>
#include <arpa/inet.h>
#include <sys/random.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include <dns_sd.h>

#include "srp.h"
#include "srp-api.h"
#include "dns-msg.h"
#define SRP_CRYPTO_MACOS_INTERNAL
#include "srp-crypto.h"

// Key is stored in an opaque data structure, for mbedtls this is an mbedtls_pk_context.
// Function to read a public key from a KEY record
// Function to validate a signature given some data and a public key (not required on client)

// Function to free a key
void
srp_keypair_free(srp_key_t *key)
{
    free(key);
}

uint16_t
srp_random16()
{
    return (uint16_t)(arc4random_uniform(65536));
}

uint32_t
srp_random32()
{
    return arc4random();
}

uint64_t
srp_random64()
{
    uint64_t ret;
    arc4random_buf(&ret, sizeof(ret));
    return ret;
}

bool
srp_randombytes(uint8_t *dest, size_t num)
{
    arc4random_buf(dest, num);
    return true;
}

static void
srp_sec_error_print(const char *reason, OSStatus status)
{
    const char *utf8 = NULL;
    CFStringRef err = SecCopyErrorMessageString(status, NULL);
    if (err != NULL) {
        utf8 = CFStringGetCStringPtr(err, kCFStringEncodingUTF8);
    }
    if (utf8 != NULL) {
        ERROR(PUB_S_SRP ": " PUB_S_SRP, reason, utf8);
    } else {
        ERROR(PUB_S_SRP ": %d", reason, (int)status);
    }
    if (err != NULL) {
        CFRelease(err);
    }
}

// Function to generate a key
static srp_key_t *
srp_get_key_internal(const char *key_name, bool delete)
{
    long two56 = 256;
    srp_key_t *key = NULL;
    OSStatus status;

    CFMutableDictionaryRef key_parameters = CFDictionaryCreateMutable(NULL, 8,
                                                                      &kCFTypeDictionaryKeyCallBacks,
                                                                      &kCFTypeDictionaryValueCallBacks);
    CFMutableDictionaryRef pubkey_parameters;

    if (key_parameters != NULL) {
        CFDictionaryAddValue(key_parameters, kSecAttrIsPermanent, kCFBooleanTrue);
        CFDictionaryAddValue(key_parameters, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
        CFNumberRef num = CFNumberCreate(NULL, kCFNumberLongType, &two56);
        CFDictionaryAddValue(key_parameters, kSecAttrKeySizeInBits, num);
        CFRelease(num);
        CFStringRef str = CFStringCreateWithCString(NULL, key_name, kCFStringEncodingUTF8);
        CFDictionaryAddValue(key_parameters, kSecAttrLabel, str);
        CFRelease(str);
        CFDictionaryAddValue(key_parameters, kSecReturnRef, kCFBooleanTrue);
        CFDictionaryAddValue(key_parameters, kSecMatchLimit, kSecMatchLimitOne);
        CFDictionaryAddValue(key_parameters, kSecClass, kSecClassKey);
        pubkey_parameters = CFDictionaryCreateMutableCopy(NULL, 8, key_parameters);
        if (pubkey_parameters != NULL) {
            CFDictionaryAddValue(key_parameters, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
            CFDictionaryAddValue(pubkey_parameters, kSecAttrKeyClass, kSecAttrKeyClassPublic);
            CFDictionaryAddValue(pubkey_parameters, kSecAttrIsExtractable, kCFBooleanTrue);
            CFDictionaryAddValue(key_parameters, kSecAttrIsExtractable, kCFBooleanTrue);
            CFDictionaryAddValue(pubkey_parameters, kSecAttrAccessible,
                                 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly);
            if (delete) {
                status = SecItemDelete(key_parameters);
                if (status == errSecSuccess) {
                    status = SecItemDelete(pubkey_parameters);
                    if (status != errSecSuccess) {
                        ERROR("srp_get_key_internal: failed to delete the public key");
                    }
                }
                key = NULL;
            } else {
                key = calloc(1, sizeof(*key));

                if (key != NULL) {
                    CFErrorRef error = NULL;

                    // See if the key is already on the keychain.
                    status = SecItemCopyMatching(key_parameters, (CFTypeRef *)&key->private);
                    if (status == errSecSuccess) {
                        status = SecItemCopyMatching(pubkey_parameters, (CFTypeRef *)&key->public);
                    } else {
                        key->private = SecKeyCreateRandomKey(key_parameters, &error);
                        if (key->private != NULL) {
                            key->public = SecKeyCopyPublicKey(key->private);
                        }
                    }
                    if (key->public == NULL || key->private == NULL) {
                        if (error != NULL) {
                            CFShow(error);
                        } else {
                            srp_sec_error_print("Failed to get key pair", status);
                        }
                        free(key);
                        key = NULL;
                    }
                }
            }
            CFRelease(key_parameters);
            CFRelease(pubkey_parameters);
        }
    }
    return key;
}

srp_key_t *
srp_get_key(const char *key_name, void *__unused os_context)
{
    return srp_get_key_internal(key_name, false);
}

// Remove an existing key
int
srp_reset_key(const char *key_name, void *__unused os_context)
{
    srp_get_key_internal(key_name, true);
    return kDNSServiceErr_NoError;
}

// void to get the length of the public key
size_t
srp_pubkey_length(srp_key_t *key)
{
    (void)key;
    return ECDSA_KEY_SIZE;
}

uint8_t
srp_key_algorithm(srp_key_t *key)
{
    (void)key;
    return dnssec_keytype_ecdsa;
}

size_t
srp_signature_length(srp_key_t *key)
{
    (void)key;
    return ECDSA_KEY_SIZE;
}

// Function to copy out the public key as binary data
size_t
srp_pubkey_copy(uint8_t *buf, size_t max, srp_key_t *key)
{
    CFErrorRef error = NULL;
    size_t ret = 0;
    CFDataRef pubkey = SecKeyCopyExternalRepresentation(key->public, &error);
    if (pubkey == NULL) {
        if (error != NULL) {
            CFShow(error);
        } else {
            ERROR("Unknown failure in SecKeyCopyExternalRepresentation");
        }
    } else {
        const uint8_t *bytes = CFDataGetBytePtr(pubkey);
        unsigned long len = (unsigned long)CFDataGetLength(pubkey);

        // Should be 04 | X | Y
        if (bytes[0] != 4) {
            ERROR("Unexpected preamble to public key: %d", bytes[0]);
        } else if (len - 1 > max) {
            ERROR("Not enough room for public key in buffer: %ld > %zd", len - 1, max);
        } else if (len - 1 != ECDSA_KEY_SIZE) {
            ERROR("Unexpected key size %ld", len - 1);
        } else {
            memcpy(buf, bytes + 1, len - 1);
            ret = ECDSA_KEY_SIZE;
        }
        CFRelease(pubkey);
    }
    return ret;
}

// Function to generate a signature given some data and a private key
int
srp_sign(uint8_t *output, size_t max, uint8_t *message, size_t msglen,
         uint8_t *rr, size_t rdlen, srp_key_t *key)
{
    CFMutableDataRef payload = NULL;
    CFDataRef signature = NULL;
    CFErrorRef error = NULL;
    const uint8_t *bytes;
    unsigned long len;
    int ret = 0;

    if (max < ECDSA_SHA256_SIG_SIZE) {
        ERROR("srp_sign: not enough space in output buffer (%lu) for signature (%d).",
              (unsigned long)max, ECDSA_SHA256_SIG_SIZE);
        return 0;
    }

    payload = CFDataCreateMutable(NULL, (CFIndex)(msglen + rdlen));
    if (payload == NULL) {
        ERROR("srp_sign: CFDataCreateMutable failed on length %zd", msglen + rdlen);
        return 0;
    }
    CFDataAppendBytes(payload, rr, (CFIndex)rdlen);
    CFDataAppendBytes(payload, message, (CFIndex)msglen);

    signature = SecKeyCreateSignature(key->private,
                                      kSecKeyAlgorithmECDSASignatureMessageX962SHA256, payload, &error);
    CFRelease(payload);
    if (error != NULL) {
        CFRelease(signature);
        CFShow(error);
        return 0;
    }
    if (signature == NULL) {
        ERROR("No error, but no signature.");
        return 0;
    }

    len = (unsigned long)CFDataGetLength(signature);
    bytes = CFDataGetBytePtr(signature);
    // The buffer is ASN.1 DER encoded as two numbers, so should be 30 <len> 02 <len> <bytes> 02 <len> <bytes>.
    if (len < 8) {
        ERROR("signature is too short to parse: %lu bytes", len);
        goto out;
    }
#define ASN1_SEQUENCE 0x30
    if (bytes[0] != ASN1_SEQUENCE) {
        ERROR("Unexpected ASN.1 type for signature: %x", bytes[0]);
        goto out;
    }
    unsigned len_sequence = bytes[1];
    if (len_sequence != len - 2) { // This is the length of the sequence, which is the remainder of the buffer
        ERROR("Unexpected ASN.1 sequence length %u when %lu bytes remain", len_sequence, len - 2);
        goto out;
    }
    const uint8_t *sequence_start = &bytes[2];
    unsigned sequence_available = len_sequence;
    int index = 0;
    while (sequence_available > 0) {
        if (index > 1) {
            ERROR("Unexpected extra datum in top-level ASN.1 sequence for signature.");
            goto out;
        }
#define ASN1_INTEGER 0x02
        if (sequence_start[0] != ASN1_INTEGER) {
            ERROR("Unexpected ASN.1 type for key half %d: %x", index, bytes[2]);
            goto out;
        }
        unsigned len_half = sequence_start[1];
        if (len_half > sequence_available - 2 || len_half > ECDSA_SHA256_SIG_PART_SIZE + 1) {
            ERROR("key half %d is too long: length %u, sequence length %u, sig part size %d",
                  index, len_half, len_sequence, ECDSA_SHA256_SIG_PART_SIZE);
            goto out;
        }
        // Now that we've bounds-checked this key half, reduce the available space by its length for
        // the next round.
        sequence_available = sequence_available - len_half - 2;

        // The key data are bignums. If the first byte of either bignum is >0x7f, it will include a leading zero
        // to make it unsigned, which we don't need.
        const uint8_t *key_half = sequence_start[2] == 0 ? &sequence_start[3] : &sequence_start[2];
        if (sequence_start[2] == 0) {
            len_half--;
        }

        unsigned long diff = ECDSA_SHA256_SIG_PART_SIZE - len_half;
        uint8_t *output_start = output + index * ECDSA_SHA256_SIG_PART_SIZE;
        if (diff > 0) {
            memset(output_start, 0, diff);
        }
        memcpy(output_start + diff, key_half, len_half);
        sequence_start = key_half + len_half;
        index++;
    }
    ret = ECDSA_SHA256_SIG_PART_SIZE * 2;

    for (int j = 0; j < 2; j++) {
        const uint8_t *buf = j == 0 ? bytes : output;
        char sigbuf[300];
        char *sigbufp = sigbuf;
        for (unsigned i = 0; i < len && (size_t)(sigbufp - sigbuf) < sizeof(sigbuf) - 3; i++) {
            snprintf(sigbufp, 4, "%02x ", buf[i]);
            sigbufp += 3;
        }
        *sigbufp = 0;
        INFO("%s: %s", j == 0 ? "input" : "output", sigbuf);
    }

out:
    if (signature != NULL) {
        CFRelease(signature);
    }
    return ret;
}

// Local Variables:
// mode: C
// tab-width: 4
// c-file-style: "bsd"
// c-basic-offset: 4
// fill-column: 108
// indent-tabs-mode: nil
// End:
