Beispiel #1
0
// Extract the RSA public key from the Key record
func (k *RR_DNSKEY) pubKeyRSA() *rsa.PublicKey {
	keybuf, err := packBase64([]byte(k.PublicKey))
	if err != nil {
		return nil
	}

	// RFC 2537/3110, section 2. RSA Public KEY Resource Records
	// Length is in the 0th byte, unless its zero, then it
	// it in bytes 1 and 2 and its a 16 bit number
	explen := uint16(keybuf[0])
	keyoff := 1
	if explen == 0 {
		explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
		keyoff = 3
	}
	pubkey := new(rsa.PublicKey)
	pubkey.N = big.NewInt(0)
	shift := (explen - 1) * 8
	for i := int(explen - 1); i >= 0; i-- {
		pubkey.E += int(keybuf[keyoff+i]) << shift
		shift -= 8
	}
	pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
	return pubkey
}
Beispiel #2
0
// msg -> rsa
func UnpackKey(k *msgs.PublicKey) *rsa.PublicKey {
	var key rsa.PublicKey
	key.N = new(big.Int)
	key.N.SetBytes(k.N)
	key.E = int(*k.E)
	return &key
}
Beispiel #3
0
// Call with tpm 2.0 and the quote handle, get the key back for serialization in AttestCertRequest.
func GetRsaKeyFromHandle(rw io.ReadWriter, handle Handle) (*rsa.PublicKey, error) {
	publicBlob, _, _, err := ReadPublic(rw, handle)
	if err != nil {
		return nil, errors.New("Can't get public key blob")
	}
	rsaParams, err := DecodeRsaBuf(publicBlob)
	publicKey := new(rsa.PublicKey)
	// TODO(jlm): read exponent from blob
	publicKey.E = 0x00010001
	M := new(big.Int)
	M.SetBytes(rsaParams.Modulus)
	publicKey.N = M
	return publicKey, nil
}
Beispiel #4
0
// Convert string to an RSA public key
func Base64ToPub(s string) (*rsa.PublicKey, os.Error) {
	if len(s) == 0 {
		return nil, nil
	}
	if !verifyCRC(s) {
		return nil, nil
	}
	s = s[0 : len(s)-1]

	enc := base64.StdEncoding
	pk := rsa.PublicKey{}

	buf := make([]byte, 4096) // shoud be big enough
	src := []byte(s)
	k := -1

	// N
	if k = firstComma(src); k < 0 {
		return nil, os.ErrorString("missing delimiter")
	}
	n, err := enc.Decode(buf, src[0:k])
	if err != nil {
		return nil, err
	}
	pk.N = &big.Int{}
	pk.N.SetBytes(buf[0:n])
	src = src[k+1:]

	// E
	n, err = enc.Decode(buf, src)
	if err != nil {
		return nil, err
	}
	pke64, err := bytesToInt64(buf[0:n])
	if err != nil {
		return nil, err
	}
	pk.E = int(pke64)

	return &pk, nil
}
Beispiel #5
0
// parseRSA parses an RSA key according to RFC 4253, section 6.6.
func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
	var w struct {
		E    *big.Int
		N    *big.Int
		Rest []byte `ssh:"rest"`
	}
	if err := Unmarshal(in, &w); err != nil {
		return nil, nil, err
	}

	if w.E.BitLen() > 24 {
		return nil, nil, errors.New("ssh: exponent too large")
	}
	e := w.E.Int64()
	if e < 3 || e&1 == 0 {
		return nil, nil, errors.New("ssh: incorrect exponent")
	}

	var key rsa.PublicKey
	key.E = int(e)
	key.N = w.N
	return (*rsaPublicKey)(&key), w.Rest, nil
}
Beispiel #6
0
// publicKeyRSA returns the RSA public key from a DNSKEY record.
func (k *RR_DNSKEY) publicKeyRSA() *rsa.PublicKey {
	keybuf, err := packBase64([]byte(k.PublicKey))
	if err != nil {
		return nil
	}

	// RFC 2537/3110, section 2. RSA Public KEY Resource Records
	// Length is in the 0th byte, unless its zero, then it
	// it in bytes 1 and 2 and its a 16 bit number
	explen := uint16(keybuf[0])
	keyoff := 1
	if explen == 0 {
		explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
		keyoff = 3
	}
	pubkey := new(rsa.PublicKey)

	pubkey.N = big.NewInt(0)
	shift := uint64((explen - 1) * 8)
	expo := uint64(0)
	for i := int(explen - 1); i > 0; i-- {
		expo += uint64(keybuf[keyoff+i]) << shift
		shift -= 8
	}
	// Remainder
	expo += uint64(keybuf[keyoff])
	if expo > 2<<31 {
		// Larger expo than supported.
		// println("dns: F5 primes (or larger) are not supported")
		return nil
	}
	pubkey.E = int(expo)

	pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
	return pubkey
}
func BuildAttestCertRequest(tpmDevice io.ReadWriter, quoteHandle Handle, endorsementHandle Handle, endorsementCert []byte,
	taoName string, ownerPw string) (*AttestCertRequest, error) {

	// Get Quote key.
	tpm2QuoteKeyBlob, tpm2QuoteKeyName, _, err := ReadPublic(tpmDevice, quoteHandle)
	if err != nil {
		return nil, err
	}
	rsaQuoteParams, err := DecodeRsaBuf(tpm2QuoteKeyBlob)
	if err != nil {
		return nil, err
	}

	quoteKey := new(rsa.PublicKey)
	quoteKey.N = new(big.Int)
	quoteKey.N.SetBytes(rsaQuoteParams.Modulus)
	quoteKey.E = int(rsaQuoteParams.Exp)

	request := new(AttestCertRequest)

	// DER encoded subject key
	derSubjectKey, err := x509.MarshalPKIXPublicKey(quoteKey)
	if err != nil {
		return nil, err
	}

	var hashedQuoteKey []byte
	if rsaQuoteParams.Hash_alg == AlgTPM_ALG_SHA1 {
		sha1Str := "sha1"
		request.HashType = &sha1Str
		sha1Hash := sha1.New()
		sha1Hash.Write([]byte(derSubjectKey))
		hashedQuoteKey = sha1Hash.Sum(nil)
	} else if rsaQuoteParams.Hash_alg == AlgTPM_ALG_SHA256 {
		sha256Str := "sha256"
		request.HashType = &sha256Str
		sha256Hash := sha256.New()
		sha256Hash.Write([]byte(derSubjectKey))
		hashedQuoteKey = sha256Hash.Sum(nil)
	} else {
		return nil, errors.New("RequestDomainQuoteCert: Quote key has unknown cert type")
	}

	sigAlg := uint16(AlgTPM_ALG_NULL)
	tpm2AttestBlob, tpm2SigBlob, err := Quote(tpmDevice, quoteHandle, ownerPw, ownerPw,
		hashedQuoteKey, []int{17, 18}, sigAlg)
	if err != nil {
		return nil, err
	}

	request.AttestBlob = tpm2AttestBlob
	request.SigBlob = tpm2SigBlob
	request.KeyName = &taoName
	request.SubjectPublicKey = derSubjectKey
	request.DerEndorsementCert = endorsementCert
	if rsaQuoteParams.Enc_alg == AlgTPM_ALG_RSA {
		rsaStr := "rsa"
		request.KeyType = &rsaStr

	} else {
		return nil, errors.New("RequestDomainQuoteCert: Bad quote key type")
	}
	request.Tpm2KeyName = tpm2QuoteKeyName
	// TODO: request.CertChain
	return request, nil
}
Beispiel #8
0
func sshToPubkey(key string) (pubkey SSHKey) {
	verbose("Converting SSH input into a public key...", 3)

	/* An RSA SSH key can have leading key options (including quoted
	 * whitespace) and trailing comments (including whitespace).  We
	 * take a short cut here and assume that if it contains the known
	 * RSA pattern, then that field must be the actual key.  This
	 * would be a false assumption if one of the comments or options
	 * contained that same pattern, but anybody who creates such a key
	 * can fo screw themselves. */
	i := strings.Index(key, OPENSSH_RSA_KEY_SUBSTRING)
	if i < 0 {
		fmt.Fprintf(os.Stderr, "Not an ssh RSA public key: '%v'\n", key)
		return
	}

	fields := strings.Split(key[i:], " ")
	decoded := decode(fields[1])
	if len(decoded) < 1 {
		fmt.Fprintf(os.Stderr, "Unable to decode key.\n")
		return
	}

	/* Based on:
	 * http://cpansearch.perl.org/src/MALLEN/Convert-SSH2-0.01/lib/Convert/SSH2.pm
	 * https://gist.github.com/mahmoudimus/1654254,
	 * http://golang.org/src/pkg/crypto/x509/x509.go
	 *
	 * See also: http://www.netmeister.org/blog/ssh2pkcs8.html
	 *
	 * The key format is base64 encoded tuples of:
	 * - four bytes representing the length of the next data field
	 * - the data field
	 *
	 * In practice, for an RSA key, we get:
	 * - four bytes [0 0 0 7]
	 * - the string "ssh-rsa" (7 bytes)
	 * - four bytes
	 * - the exponent
	 * - four bytes
	 * - the modulus
	 */

	var k rsa.PublicKey
	n := 0
	for len(decoded) > 4 {
		var dlen uint32
		bbuf := bytes.NewReader(decoded[:4])
		err := binary.Read(bbuf, binary.BigEndian, &dlen)
		if err != nil {
			fmt.Printf("%v\n", err)
			continue
		}

		chunklen := int(dlen) + 4
		if len(decoded) < chunklen {
			fmt.Fprintf(os.Stderr, "Invalid data while trying to extract public key.\n")
			fmt.Fprintf(os.Stderr, "Maybe a corrupted key?\n%v\n", key)
			return
		}

		data := decoded[4:chunklen]
		decoded = decoded[chunklen:]

		switch n {
		case 0:
			if ktype := fmt.Sprintf("%s", data); ktype != "ssh-rsa" {
				fmt.Fprintf(os.Stderr, "Unsupported key type (%v).\n", ktype)
				return
			}
		case 1:
			i := new(big.Int)
			i.SetString(fmt.Sprintf("0x%v", hex.EncodeToString(data)), 0)
			k.E = int(i.Int64())
		case 2:
			i := new(big.Int)
			/* The value in this field is signed, so the first
			 * byte should be 0, so we strip it. */
			i.SetString(fmt.Sprintf("0x%v", hex.EncodeToString(data[1:])), 0)
			k.N = i
		}
		n++
	}

	pubkey.Key = k
	pubkey.Fingerprint = getFingerPrint(k)

	return
}
Beispiel #9
0
func main() {
	if len(os.Args) > 1 {
		log.Fatal("Unexpected arguments.  This program can only read input from stdin.")
	}

	input, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		log.Fatal(err)
	}

	key := string(input)

	/* An RSA SSH key can have leading key options (including quoted
	 * whitespace) and trailing comments (including whitespace).  We
	 * take a short cut here and assume that if it contains the known
	 * RSA pattern, then that field must be the actual key.  This
	 * would be a false assumption if one of the comments or options
	 * contained that same pattern, but anybody who creates such a key
	 * can fo screw themselves. */
	i := strings.Index(key, "ssh-rsa AAAAB3NzaC1")
	if i < 0 {
		log.Fatal("Input does not look like a valid SSH RSA key.")
	}

	fields := strings.Split(key[i:], " ")
	decoded, err := base64.StdEncoding.DecodeString(fields[1])
	if err != nil {
		log.Fatal("Unable to decode key: %v", err)
	}

	/* Based on:
	 * http://cpansearch.perl.org/src/MALLEN/Convert-SSH2-0.01/lib/Convert/SSH2.pm
	 * https://gist.github.com/mahmoudimus/1654254,
	 * http://golang.org/src/pkg/crypto/x509/x509.go
	 *
	 * The key format is base64 encoded tuples of:
	 * - four bytes representing the length of the next data field
	 * - the data field
	 *
	 * In practice, for an RSA key, we get:
	 * - four bytes [0 0 0 7]
	 * - the string "ssh-rsa" (7 bytes)
	 * - four bytes
	 * - the exponent
	 * - four bytes
	 * - the modulus
	 */
	n := 0
	var pubkey rsa.PublicKey
	for len(decoded) > 0 {
		var dlen uint32
		bbuf := bytes.NewReader(decoded[:4])
		err := binary.Read(bbuf, binary.BigEndian, &dlen)
		if err != nil {
			log.Fatal(err)
		}

		data := decoded[4 : int(dlen)+4]
		decoded = decoded[4+int(dlen):]

		if n == 0 {
			if ktype := fmt.Sprintf("%s", data); ktype != "ssh-rsa" {
				log.Fatal("Unsupported key type (%v).", ktype)
			}
		} else if n == 1 {
			i := new(big.Int)
			i.SetString(fmt.Sprintf("0x%v", hex.EncodeToString(data)), 0)
			pubkey.E = int(i.Int64())
		} else if n == 2 {
			i := new(big.Int)
			/* The value in this field is signed, so the first
			 * byte should be 0, so we strip it. */
			i.SetString(fmt.Sprintf("0x%v", hex.EncodeToString(data[1:])), 0)
			pubkey.N = i
			break
		}
		n += 1
	}

	enc, err := asn1.Marshal(pubkey)
	if err != nil {
		log.Fatal("Unable to marshal pubkey (%v): %v", pubkey, err)
	}
	bitstring := asn1.BitString{enc, len(enc) * 8}

	type AlgorithmIdentifier struct {
		Algorithm  asn1.ObjectIdentifier
		Parameters asn1.RawValue
	}

	var null = asn1.RawValue{Tag: 5}
	var pkid = AlgorithmIdentifier{asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}, null}

	type keyseq struct {
		Algorithm AlgorithmIdentifier
		BitString asn1.BitString
	}
	ks := keyseq{pkid, bitstring}

	enc, err = asn1.Marshal(ks)
	if err != nil {
		log.Fatal("Unable to marshal pubkey (%v): %v", pubkey, err)
	}

	fmt.Printf("-----BEGIN PUBLIC KEY-----\n")
	out := base64.StdEncoding.EncodeToString(enc)
	for len(out) > MAX_COLUMNS {
		fmt.Printf("%v\n", out[:MAX_COLUMNS])
		out = out[MAX_COLUMNS:]
	}
	fmt.Printf("%v\n", out)
	fmt.Printf("-----END PUBLIC KEY-----\n")
}
Beispiel #10
0
// Combined Endorsement/Activate test
func TestCombinedEndorsementTest(t *testing.T) {
	hash_alg_id := uint16(AlgTPM_ALG_SHA1)

	// Open tpm
	rw, err := OpenTPM("/dev/tpm0")
	if err != nil {
		fmt.Printf("OpenTPM failed %s\n", err)
		return
	}

	// Flushall
	err = Flushall(rw)
	if err != nil {
		t.Fatal("Flushall failed\n")
	}

	// CreatePrimary
	var empty []byte
	primaryparms := RsaParams{uint16(AlgTPM_ALG_RSA), uint16(AlgTPM_ALG_SHA1),
		uint32(0x00030072), empty, uint16(AlgTPM_ALG_AES), uint16(128),
		uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL), uint16(0),
		uint16(2048), uint32(0x00010001), empty}
	parent_handle, public_blob, err := CreatePrimary(rw,
		uint32(OrdTPM_RH_OWNER), []int{0x7}, "", "", primaryparms)
	if err != nil {
		t.Fatal("CreatePrimary fails")
	}
	fmt.Printf("CreatePrimary succeeded\n")
	endorseParams, err := DecodeRsaArea(public_blob)
	if err != nil {
		t.Fatal("DecodeRsaBuf fails", err)
	}

	// CreateKey
	keyparms := RsaParams{uint16(AlgTPM_ALG_RSA), uint16(AlgTPM_ALG_SHA1),
		uint32(0x00030072), empty, uint16(AlgTPM_ALG_AES), uint16(128),
		uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL), uint16(0),
		uint16(2048), uint32(0x00010001), empty}
	private_blob, public_blob, err := CreateKey(rw, uint32(parent_handle),
		[]int{7}, "", "01020304", keyparms)
	if err != nil {
		t.Fatal("CreateKey fails")
	}
	fmt.Printf("CreateKey succeeded\n")

	// Load
	key_handle, _, err := Load(rw, parent_handle, "", "",
		public_blob, private_blob)
	if err != nil {
		t.Fatal("Load fails")
	}
	fmt.Printf("Load succeeded\n")

	// ReadPublic
	_, name, _, err := ReadPublic(rw, key_handle)
	if err != nil {
		t.Fatal("ReadPublic fails")
	}
	fmt.Printf("ReadPublic succeeded\n")

	// Generate Credential
	credential := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10}
	fmt.Printf("Credential: %x\n", credential)

	// Internal MakeCredential
	credBlob, encrypted_secret0, err := InternalMakeCredential(rw, parent_handle, credential, name)
	if err != nil {
		FlushContext(rw, key_handle)
		FlushContext(rw, parent_handle)
		t.Fatal("Can't InternalMakeCredential\n")
	}

	// ActivateCredential
	recovered_credential1, err := ActivateCredential(rw, key_handle, parent_handle,
		"01020304", "", credBlob, encrypted_secret0)
	if err != nil {
		FlushContext(rw, key_handle)
		FlushContext(rw, parent_handle)
		t.Fatal("Can't ActivateCredential\n")
	}
	if bytes.Compare(credential, recovered_credential1) != 0 {
		FlushContext(rw, key_handle)
		FlushContext(rw, parent_handle)
		t.Fatal("Credential and recovered credential differ\n")
	}
	fmt.Printf("InternalMake/Activate test succeeds\n\n")

	protectorPublic := new(rsa.PublicKey)
	protectorPublic.E = 0x00010001
	M := new(big.Int)
	M.SetBytes(endorseParams.Modulus)
	protectorPublic.N = M

	// MakeCredential
	encrypted_secret, encIdentity, integrityHmac, err := MakeCredential(
		protectorPublic, hash_alg_id, credential, name)
	if err != nil {
		FlushContext(rw, key_handle)
		FlushContext(rw, parent_handle)
		t.Fatal("Can't MakeCredential\n")
	}

	// ActivateCredential
	recovered_credential2, err := ActivateCredential(rw,
		key_handle, parent_handle, "01020304", "",
		append(integrityHmac, encIdentity...), encrypted_secret)
	if err != nil {
		FlushContext(rw, key_handle)
		FlushContext(rw, parent_handle)
		t.Fatal("Can't ActivateCredential\n")
	}
	if bytes.Compare(credential, recovered_credential2) != 0 {
		FlushContext(rw, key_handle)
		FlushContext(rw, parent_handle)
		t.Fatal("Credential and recovered credential differ\n")
	}
	fmt.Printf("Make/Activate test succeeds\n")

	// Flush
	FlushContext(rw, key_handle)
}