...

Source file src/github.com/sassoftware/relic/token/p11token/list.go

Documentation: github.com/sassoftware/relic/token/p11token

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package p11token
    18  
    19  import (
    20  	"bytes"
    21  	"crypto"
    22  	"crypto/x509"
    23  	"encoding/base64"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"strings"
    28  
    29  	"github.com/miekg/pkcs11"
    30  	"github.com/sassoftware/relic/lib/x509tools"
    31  	"github.com/sassoftware/relic/token"
    32  )
    33  
    34  var classNames = map[uint]string{
    35  	pkcs11.CKO_DATA:              "data",
    36  	pkcs11.CKO_CERTIFICATE:       "certificate",
    37  	pkcs11.CKO_PUBLIC_KEY:        "public_key",
    38  	pkcs11.CKO_PRIVATE_KEY:       "private_key",
    39  	pkcs11.CKO_SECRET_KEY:        "secret_key",
    40  	pkcs11.CKO_HW_FEATURE:        "hw_feature",
    41  	pkcs11.CKO_DOMAIN_PARAMETERS: "domain_parameters",
    42  	pkcs11.CKO_MECHANISM:         "mechanism",
    43  	pkcs11.CKO_OTP_KEY:           "otp_key",
    44  }
    45  
    46  var keyTypes = map[uint]string{
    47  	pkcs11.CKK_RSA: "rsa",
    48  	pkcs11.CKK_DSA: "dsa",
    49  	pkcs11.CKK_EC:  "ec",
    50  }
    51  
    52  func (tok *Token) ListKeys(opts token.ListOptions) error {
    53  	filterKeyId, err := parseKeyID(opts.ID)
    54  	if err != nil {
    55  		return errors.New("invalid filter id")
    56  	}
    57  	tok.mutex.Lock()
    58  	defer tok.mutex.Unlock()
    59  	if err := tok.ctx.FindObjectsInit(tok.sh, nil); err != nil {
    60  		return err
    61  	}
    62  	defer tok.ctx.FindObjectsFinal(tok.sh)
    63  	for {
    64  		objects, _, err := tok.ctx.FindObjects(tok.sh, 1)
    65  		if err != nil {
    66  			return err
    67  		} else if len(objects) == 0 {
    68  			break
    69  		}
    70  		for _, handle := range objects {
    71  			objId := tok.getAttribute(handle, pkcs11.CKA_ID)
    72  			label := tok.getAttribute(handle, pkcs11.CKA_LABEL)
    73  			if opts.Label != "" && string(label) != opts.Label {
    74  				continue
    75  			}
    76  			if len(filterKeyId) != 0 && !bytes.Equal(filterKeyId, objId) {
    77  				continue
    78  			}
    79  			fmt.Fprintf(opts.Output, "handle 0x%08x:\n", handle)
    80  			class := attrToInt(tok.getAttribute(handle, pkcs11.CKA_CLASS))
    81  			if name := classNames[class]; name != "" {
    82  				fmt.Fprintf(opts.Output, " class:   %s\n", name)
    83  			} else {
    84  				fmt.Fprintf(opts.Output, " class:   0x%08x\n", class)
    85  			}
    86  			if len(objId) > 0 {
    87  				fmt.Fprintf(opts.Output, " id:      %s\n", formatKeyID(objId))
    88  			}
    89  			if len(label) > 0 {
    90  				fmt.Fprintf(opts.Output, " label:   %s\n", label)
    91  			}
    92  			switch class {
    93  			case pkcs11.CKO_PUBLIC_KEY:
    94  				tok.printKey(opts, handle)
    95  			case pkcs11.CKO_PRIVATE_KEY:
    96  				tok.printKey(opts, handle)
    97  			case pkcs11.CKO_CERTIFICATE:
    98  				tok.printCertificate(opts, handle)
    99  			case pkcs11.CKO_DATA:
   100  				value := tok.getAttribute(handle, pkcs11.CKA_VALUE)
   101  				fmt.Fprintf(opts.Output, " size:    %d\n", len(value))
   102  				if opts.Values {
   103  					fmt.Fprintln(opts.Output, " value: !!binary |")
   104  					dumpData(opts.Output, value)
   105  				}
   106  			}
   107  			fmt.Fprintln(opts.Output)
   108  		}
   109  	}
   110  	return nil
   111  }
   112  
   113  func (tok *Token) printKey(opts token.ListOptions, handle pkcs11.ObjectHandle) {
   114  	keyType := attrToInt(tok.getAttribute(handle, pkcs11.CKA_KEY_TYPE))
   115  	if name := keyTypes[keyType]; name != "" {
   116  		fmt.Fprintf(opts.Output, " type:    %s\n", name)
   117  	} else {
   118  		fmt.Fprintf(opts.Output, " type:    0x%08x\n", keyType)
   119  	}
   120  	switch keyType {
   121  	case pkcs11.CKK_RSA:
   122  		if n := tok.getAttribute(handle, pkcs11.CKA_MODULUS); len(n) != 0 {
   123  			fmt.Fprintf(opts.Output, " bits:    %d\n", len(n)*8)
   124  			if opts.Values {
   125  				fmt.Fprintf(opts.Output, " n:       0x%x\n", bytesToBig(n))
   126  			}
   127  		}
   128  		if e := tok.getAttribute(handle, pkcs11.CKA_PUBLIC_EXPONENT); len(e) != 0 && opts.Values {
   129  			fmt.Fprintf(opts.Output, " e:       %s\n", bytesToBig(e))
   130  		}
   131  	case pkcs11.CKK_EC:
   132  		ecparams := tok.getAttribute(handle, pkcs11.CKA_EC_PARAMS)
   133  		if len(ecparams) == 0 {
   134  			return
   135  		}
   136  		curve, err := x509tools.CurveByDer(ecparams)
   137  		if err != nil {
   138  			fmt.Fprintf(opts.Output, " curve:   %x\n", ecparams)
   139  			return
   140  		}
   141  		fmt.Fprintf(opts.Output, " bits:    %d\n", curve.Bits)
   142  		ecpoint := tok.getAttribute(handle, pkcs11.CKA_EC_POINT)
   143  		if len(ecpoint) > 0 && opts.Values {
   144  			x, y := x509tools.DerToPoint(curve.Curve, ecpoint)
   145  			if x != nil {
   146  				fmt.Fprintf(opts.Output, " x:       0x%x\n", x)
   147  				fmt.Fprintf(opts.Output, " y:       0x%x\n", y)
   148  			}
   149  		}
   150  	}
   151  }
   152  
   153  func (tok *Token) printCertificate(opts token.ListOptions, handle pkcs11.ObjectHandle) {
   154  	blob := tok.getAttribute(handle, pkcs11.CKA_VALUE)
   155  	if len(blob) == 0 {
   156  		fmt.Fprintln(opts.Output, "certificate is missing")
   157  		return
   158  	}
   159  	cert, err := x509.ParseCertificate(blob)
   160  	if err != nil {
   161  		fmt.Fprintln(opts.Output, "certificate is invalid:", err)
   162  	}
   163  	d := crypto.SHA1.New()
   164  	d.Write(blob)
   165  	fmt.Fprintf(opts.Output, " subject: %s\n issuer:  %s\n sha1:    %x\n", x509tools.FormatSubject(cert), x509tools.FormatIssuer(cert), d.Sum(nil))
   166  	if opts.Values {
   167  		fmt.Fprintln(opts.Output, " value: |\n  -----BEGIN CERTIFICATE-----")
   168  		dumpData(opts.Output, blob)
   169  		fmt.Fprintln(opts.Output, "  -----END CERTIFICATE-----")
   170  	}
   171  }
   172  
   173  func formatKeyID(keyID []byte) string {
   174  	chunks := make([]string, len(keyID))
   175  	for i, j := range keyID {
   176  		chunks[i] = fmt.Sprintf("%02x", j)
   177  	}
   178  	return strings.Join(chunks, ":")
   179  }
   180  
   181  func dumpData(w io.Writer, d []byte) error {
   182  	encoded := base64.StdEncoding.EncodeToString(d)
   183  	for len(encoded) > 0 {
   184  		n := 64
   185  		if n > len(encoded) {
   186  			n = len(encoded)
   187  		}
   188  		if _, err := fmt.Fprintln(w, " ", encoded[:n]); err != nil {
   189  			return err
   190  		}
   191  		encoded = encoded[n:]
   192  	}
   193  	return nil
   194  }
   195  

View as plain text