// Copyright 2016 The BoringSSL Authors
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

package runner

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/asn1"
	"errors"
)

// TestShimTicketKey is the testing key assumed for the shim.
var TestShimTicketKey = make([]byte, 48)

func DecryptShimTicket(in []byte) ([]byte, error) {
	name := TestShimTicketKey[:16]
	macKey := TestShimTicketKey[16:32]
	encKey := TestShimTicketKey[32:48]

	h := hmac.New(sha256.New, macKey)

	block, err := aes.NewCipher(encKey)
	if err != nil {
		panic(err)
	}

	if len(in) < len(name)+block.BlockSize()+1+h.Size() {
		return nil, errors.New("tls: shim ticket too short")
	}

	// Check the key name.
	if !bytes.Equal(name, in[:len(name)]) {
		return nil, errors.New("tls: shim ticket name mismatch")
	}

	// Check the MAC at the end of the ticket.
	mac := in[len(in)-h.Size():]
	in = in[:len(in)-h.Size()]
	h.Write(in)
	if !hmac.Equal(mac, h.Sum(nil)) {
		return nil, errors.New("tls: shim ticket MAC mismatch")
	}

	// The MAC covers the key name, but the encryption does not.
	in = in[len(name):]

	// Decrypt in-place.
	iv := in[:block.BlockSize()]
	in = in[block.BlockSize():]
	if l := len(in); l == 0 || l%block.BlockSize() != 0 {
		return nil, errors.New("tls: ticket ciphertext not a multiple of the block size")
	}
	out := make([]byte, len(in))
	cbc := cipher.NewCBCDecrypter(block, iv)
	cbc.CryptBlocks(out, in)

	// Remove the padding.
	pad := int(out[len(out)-1])
	if pad == 0 || pad > block.BlockSize() || pad > len(in) {
		return nil, errors.New("tls: bad shim ticket CBC pad")
	}

	for i := 0; i < pad; i++ {
		if out[len(out)-1-i] != byte(pad) {
			return nil, errors.New("tls: bad shim ticket CBC pad")
		}
	}

	return out[:len(out)-pad], nil
}

func EncryptShimTicket(in []byte) []byte {
	name := TestShimTicketKey[:16]
	macKey := TestShimTicketKey[16:32]
	encKey := TestShimTicketKey[32:48]

	h := hmac.New(sha256.New, macKey)

	block, err := aes.NewCipher(encKey)
	if err != nil {
		panic(err)
	}

	// Use the zero IV for rewritten tickets.
	iv := make([]byte, block.BlockSize())
	cbc := cipher.NewCBCEncrypter(block, iv)
	pad := block.BlockSize() - (len(in) % block.BlockSize())

	out := make([]byte, 0, len(name)+len(iv)+len(in)+pad+h.Size())
	out = append(out, name...)
	out = append(out, iv...)
	out = append(out, in...)
	for i := 0; i < pad; i++ {
		out = append(out, byte(pad))
	}

	ciphertext := out[len(name)+len(iv):]
	cbc.CryptBlocks(ciphertext, ciphertext)

	h.Write(out)
	return h.Sum(out)
}

const asn1Constructed = 0x20

func parseDERElement(in []byte) (tag byte, body, rest []byte, ok bool) {
	rest = in
	if len(rest) < 1 {
		return
	}

	tag = rest[0]
	rest = rest[1:]

	if tag&0x1f == 0x1f {
		// Long-form tags not supported.
		return
	}

	if len(rest) < 1 {
		return
	}

	length := int(rest[0])
	rest = rest[1:]
	if length > 0x7f {
		lengthLength := length & 0x7f
		length = 0
		if lengthLength == 0 {
			// No indefinite-length encoding.
			return
		}

		// Decode long-form lengths.
		for lengthLength > 0 {
			if len(rest) < 1 || (length<<8)>>8 != length {
				return
			}
			if length == 0 && rest[0] == 0 {
				// Length not minimally-encoded.
				return
			}
			length <<= 8
			length |= int(rest[0])
			rest = rest[1:]
			lengthLength--
		}

		if length < 0x80 {
			// Length not minimally-encoded.
			return
		}
	}

	if len(rest) < length {
		return
	}

	body = rest[:length]
	rest = rest[length:]
	ok = true
	return
}

func SetShimTicketVersion(in []byte, vers uint16) ([]byte, error) {
	plaintext, err := DecryptShimTicket(in)
	if err != nil {
		return nil, err
	}

	tag, session, _, ok := parseDERElement(plaintext)
	if !ok || tag != asn1.TagSequence|asn1Constructed {
		return nil, errors.New("tls: could not decode shim session")
	}

	// Skip the session version.
	tag, _, session, ok = parseDERElement(session)
	if !ok || tag != asn1.TagInteger {
		return nil, errors.New("tls: could not decode shim session")
	}

	// Next field is the protocol version.
	tag, version, _, ok := parseDERElement(session)
	if !ok || tag != asn1.TagInteger {
		return nil, errors.New("tls: could not decode shim session")
	}

	// This code assumes both old and new versions are encoded in two
	// bytes. This isn't quite right as INTEGERs are minimally-encoded, but
	// we do not need to support other caess for now.
	if len(version) != 2 || vers < 0x80 || vers >= 0x8000 {
		return nil, errors.New("tls: unsupported version in shim session")
	}

	version[0] = byte(vers >> 8)
	version[1] = byte(vers)

	return EncryptShimTicket(plaintext), nil
}

func SetShimTicketCipherSuite(in []byte, id uint16) ([]byte, error) {
	plaintext, err := DecryptShimTicket(in)
	if err != nil {
		return nil, err
	}

	tag, session, _, ok := parseDERElement(plaintext)
	if !ok || tag != asn1.TagSequence|asn1Constructed {
		return nil, errors.New("tls: could not decode shim session")
	}

	// Skip the session version.
	tag, _, session, ok = parseDERElement(session)
	if !ok || tag != asn1.TagInteger {
		return nil, errors.New("tls: could not decode shim session")
	}

	// Skip the protocol version.
	tag, _, session, ok = parseDERElement(session)
	if !ok || tag != asn1.TagInteger {
		return nil, errors.New("tls: could not decode shim session")
	}

	// Next field is the cipher suite.
	tag, cipherSuite, _, ok := parseDERElement(session)
	if !ok || tag != asn1.TagOctetString || len(cipherSuite) != 2 {
		return nil, errors.New("tls: could not decode shim session")
	}

	cipherSuite[0] = byte(id >> 8)
	cipherSuite[1] = byte(id)

	return EncryptShimTicket(plaintext), nil
}
