#!/usr/bin/env python
"""
Securely back up private keys from one Cryptech HSM to another.
This works by having the destination HSM (the one importing keys)
create an RSA keypair (the "KEKEK"), the public key of which can then
be imported into the source HSM (the one exporting keys) and used to
encrypt AES key encryption keys (KEKs) which in turn can be used to
wrap the private keys being transfered. Transfers are encoded in
JSON; the underlying ASN.1 formats are SubjectPublicKeyInfo (KEKEK
public key) and PKCS #8 EncryptedPrivateKeyInfo (everything else).
NOTE WELL: while this process makes it POSSIBLE to back up keys
securely, it is not sufficient by itself: the operator MUST make
sure only to export keys using a KEKEK known to have been generated by
the target HSM. See the unit tests in the source repository for
an example of how to fake this in a few lines of Python.
We also implement a software-based variant on this backup mechanism,
for cases where there is no second HSM. The protocol is much the
same, but the KEKEK is generated in software and encrypted using a
symmetric key derived from a passphrase using PBKDF2. This requires
the PyCrypto library, and is only as secure as memory on the machine
where you're running it (so it's theoretically vulnerable to root or
anybody with access to /dev/mem). Don't use this mode unless you
understand the risks, and see the "NOTE WELL" above.
YOU HAVE BEEN WARNED. Be careful out there.
"""
# Diagram of the trivial protocol we're using:
#
# SOURCE HSM DESTINATION HSM
#
# Generate and export KEKEK:
# hal_rpc_pkey_generate_rsa()
# hal_rpc_pkey_get_public_key()
#
# Load KEKEK public <--------- Export KEKEK public
# hal_rpc_pkey_load()
# hal_rpc_pkey_export()
#
# Export PKCS #8 and KEK ----------> Load PKCS #8 and KEK, import key
# hal_rpc_pkey_import()
import sys
import json
import uuid
import atexit
import getpass
import argparse
from cryptech.libhal import *
def main():
parser = argparse.ArgumentParser(
formatter_class = argparse.RawDescriptionHelpFormatter,
description = __doc__)
subparsers = parser.add_subparsers(
title = "Commands (use \"--help\" after command name for help with individual commands)",
metavar = "")
setup_parser = defcmd(subparsers, cmd_setup)
export_parser = defcmd(subparsers, cmd_export)
import_parser = defcmd(subparsers, cmd_import)
setup_mutex_group = setup_parser.add_mutually_exclusive_group()
parser.add_argument(
"-p", "--pin",
help = "wheel PIN")
setup_mutex_group.add_argument(
"-n", "--new",
action = "store_true",
help = "force creation of new KEKEK")
setup_mutex_group.add_argument(
"-u", "--uuid",
help = "UUID of existing KEKEK to use")
setup_mutex_group.add_argument(
"-s", "--soft-backup",
action = "store_true",
help = "software-based backup, see warnings")
setup_parser.add_argument(
"-k", "--keylen",
type = int,
default = 2048,
help = "length of new KEKEK if we need to create one")
setup_parser.add_argument(
"-o", "--output",
type = argparse.FileType("w"),
default = "-",
help = "output file")
export_parser.add_argument(
"-i", "--input",
type = argparse.FileType("r"),
default = "-",
help = "input file")
export_parser.add_argument(
"-o", "--output",
type = argparse.FileType("w"),
default = "-",
help = "output file")
import_parser.add_argument(
"-i", "--input",
type = argparse.FileType("r"),
default = "-",
help = "input file")
args = parser.parse_args()
hsm = HSM()
try:
hsm.login(HAL_USER_WHEEL, args.pin or getpass.getpass("Wheel PIN: "))
except HALError as e:
sys.exit("Couldn't log into HSM: {}".format(e))
try:
sys.exit(args.func(args, hsm))
finally:
hsm.logout()
def defcmd(subparsers, func):
assert func.__name__.startswith("cmd_")
subparser = subparsers.add_parser(func.__name__[4:],
description = func.__doc__,
help = func.__doc__.strip().splitlines()[0])
subparser.set_defaults(func = func)
return subparser
def b64(bytes):
return bytes.encode("base64").splitlines()
def b64join(lines):
return "".join(lines).decode("base64")
def cmd_setup(args, hsm):
"""
Set up backup HSM for subsequent import.
Generates an RSA keypair with appropriate usage settings
to use as a key-encryption-key-encryption-key (KEKEK), and
writes the KEKEK to a JSON file for transfer to primary HSM.
"""
result = {}
uuids = []
if args.soft_backup:
SoftKEKEK.generate(args, result)
elif args.uuid:
uuids.append(args.uuid)
elif not args.new:
uuids.extend(hsm.pkey_match(
type = HAL_KEY_TYPE_RSA_PRIVATE,
mask = HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | HAL_KEY_FLAG_TOKEN,
flags = HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | HAL_KEY_FLAG_TOKEN))
for uuid in uuids:
with hsm.pkey_open(uuid) as kekek:
if kekek.key_type != HAL_KEY_TYPE_RSA_PRIVATE:
sys.stderr.write("Key {} is not an RSA private key\n".format(uuid))
elif (kekek.key_flags & HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT) == 0:
sys.stderr.write("Key {} does not allow key encipherment\n".format(uuid))
else:
result.update(kekek_uuid = str(kekek.uuid),
kekek_pubkey = b64(kekek.public_key))
break
if not result and not args.uuid:
with hsm.pkey_generate_rsa(
keylen = args.keylen,
flags = HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | HAL_KEY_FLAG_TOKEN) as kekek:
result.update(kekek_uuid = str(kekek.uuid),
kekek_pubkey = b64(kekek.public_key))
if not result:
sys.exit("Could not find suitable KEKEK")
if args.soft_backup:
result.update(comment = "KEKEK software keypair")
else:
result.update(comment = "KEKEK public key")
json.dump(result, args.output, indent = 4, sort_keys = True)
args.output.write("\n")
def key_flag_names(flags):
names = dict(digitalsignature = HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE,
keyencipherment = HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT,
dataencipherment = HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT,
token = HAL_KEY_FLAG_TOKEN,
public = HAL_KEY_FLAG_PUBLIC,
exportable = HAL_KEY_FLAG_EXPORTABLE)
return ", ".join(sorted(k for k, v in names.iteritems() if (flags & v) != 0))
def cmd_export(args, hsm):
"""
Export encrypted keys from primary HSM.
Takes a JSON file containing KEKEK (generated by running this
script's "setup" command against the backup HSM<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle6</string>
<string>159.2.0.222945</string>
</array>
<key>AutoAdjust</key>
<false/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {818, 571}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-01-08 13:51:19 +0000</string>
<key>Creator</key>
<string>Jakob Schlyter</string>
<key>DisplayScale</key>
<string>1.0000 cm = 1.0000 cm</string>
<key>FileType</key>
<string>flat</string>
<key>GraphDocumentVersion</key>
<integer>12</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>235</integer>
</dict>
<key>ID</key>
<integer>255</integer>
<key>Points</key>
<array>
<string>{541.41732965961216, 340.15748308249351}</string>
<string>{541.41732965961216, 299.05508109346147}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>254</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{541.41732965961205, 348.66142016752497}, {99.212599325367762, 28.346456527709961}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>252</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 RPKI}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{541.41732965961216, 377.00787669523493}, {99.212599325367762, 28.346456527709961}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>251</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 SAML}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{442.20473033424423, 377.00787669523493}, {99.212599325367762, 28.346456527709961}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>250</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 X.509/PKIX\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\fs16 \cf0 CSR/CRL/OCSP}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{442.20473033424423, 348.66142016752497}, {99.212599325367762, 28.346456527709961}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>249</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 DNSSEC}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>233</integer>
</dict>
<key>ID</key>
<integer>248</integer>
<key>Points</key>
<array>
<string>{103.90070816388307, 279.21258109346149}</string>
<string>{201.2598458333278, 279.21258109346149}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>245</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>257</integer>
</dict>
<key>ID</key>
<integer>247</integer>
<key>Points</key>
<array>
<string>{103.90070816388307, 279.21258109346149}</string>
<string>{201.25984583332797, 331.65352655741185}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>245</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>261</integer>
</dict>
<key>ID</key>
<integer>246</integer>
<key>Points</key>
<array>
<string>{103.90070816388307, 279.21258109346149}</string>
<string>{201.25984583332797, 226.77163562951122}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>245</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{54.294408501199186, 259.37008109346152}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>245</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Application}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>241</integer>
</dict>
<key>ID</key>
<integer>242</integer>
<key>Points</key>
<array>
<string>{591.02362932229607, 279.21258109346149}</string>
<string>{620.78740880113878, 279.21258109346149}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>235</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{620.78740880113878, 259.37008109346152}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>241</integer>
<key>Magnets</key>
<array>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Signer}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>235</integer>
<key>Info</key>
<integer>11</integer>
</dict>
<key>ID</key>
<integer>239</integer>
<key>Points</key>
<array>
<string>{399.6850444840635, 279.21258109346149}</string>
<string>{491.81102999692826, 279.21258109346149}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>233</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>235</integer>
<key>Info</key>
<integer>10</integer>
</dict>
<key>ID</key>
<integer>238</integer>
<key>Points</key>
<array>
<string>{399.68504448406367, 331.65352655741185}</string>
<string>{491.81102999692826, 289.13383109346148}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>258</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>235</integer>
<key>Info</key>
<integer>12</integer>
</dict>
<key>ID</key>
<integer>237</integer>
<key>Points</key>
<array>
<string>{399.68504448406361, 226.77163562951122}</string>
<string>{491.81102999692831, 269.29133109346151}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>260</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>Head</key>
<dict>
<key>ID</key>
<integer>235</integer>
</dict>
<key>ID</key>
<integer>236</integer>
<key>Points</key>
<array>
<string>{541.41732965961216, 205.29918035556122}</string>
<string>{541.41732965961216, 259.37008109346152}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<false/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>13</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{505.41732965961216, 170.07874201939808}, {72, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>13</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>DocumentShape</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Module\
Policy}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{491.81102999692826, 259.37008109346152}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>235</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Inspection Module}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>Group</string>
<key>Graphics</key>
<array>
<dict>
<key>Bounds</key>
<string>{{201.25984583332797, 311.81102655741182}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>257</integer>
<key>Magnets</key>
<array>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 CKM_SHA256}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{300.47244515869585, 311.81102655741182}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>258</integer>
<key>Magnets</key>
<array>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 CKM_ECDSA}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
</array>
<key>ID</key>
<integer>256</integer>
</dict>
<dict>
<key>Bounds</key>
<string>{{201.2598458333278, 259.37008109346152}, {198.42519865073572, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>233</integer>
<key>Magnets</key>
<array>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 CKM_SHA256_RSA_PKCS}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Class</key>
<string>Group</string>
<key>Graphics</key>
<array>
<dict>
<key>Bounds</key>
<string>{{300.47244515869585, 206.92913562951122}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>260</integer>
<key>Magnets</key>
<array>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 CKM_RSA_PKCS}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{201.25984583332797, 206.92913562951122}, {99.212599325367762, 39.685000000000002}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>261</integer>
<key>Magnets</key>
<array>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 CKM_SHA256}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
</array>
<key>ID</key>
<integer>259</integer>
</dict>
<dict>
<key>Bounds</key>
<string>{{184.89250291133504, 195.05909091062659}, {231.1598844947213, 181.94878578460836}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FontInfo</key>
<dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>8</real>
</dict>
<key>ID</key>
<integer>243</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>0.901961</string>
<key>g</key>
<string>0.901961</string>
<key>r</key>
<string>0.901961</string>
</dict>
</dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Align</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\f0\fs16 \cf0 PKCS#11}</string>
</dict>
<key>TextPlacement</key>
<integer>2</integer>
</dict>
<dict>
<key>Bounds</key>
<string>{{435.82677752047073, 340.15748308249346}, {211.18110427828282, 86.456693697820469}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>254</integer>
<key>Magnets</key>
<array>
<string>{-0.59628479399994394, -1.1925695879998879}</string>
<string>{0, -1.3333333333333333}</string>
<string>{0.59628479399994572, -1.1925695879998872}</string>
<string>{1.1925695879998883, -0.59628479399994305}</string>
<string>{1.3333333333333335, 0}</string>
<string>{1.1925695879998894, 0.5962847939999415}</string>
<string>{0.59628479399994649, 1.1925695879998865}</string>
<string>{0, 1.3333333333333333}</string>
<string>{-0.59628479399994472, 1.1925695879998872}</string>
<string>{-1.1925695879998888, 0.59628479399994228}</string>
<string>{-1.3333333333333333, 0}</string>
<string>{-1.1925695879998879, -0.59628479399994394}</string>
</array>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>0.901961</string>
<key>g</key>
<string>0.901961</string>
<key>r</key>
<string>0.901961</string>
</dict>
</dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Align</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0\i\fs16 \cf0 Content Inspection Modules}</string>
</dict>
<key>TextPlacement</key>
<integer>2</integer>
</dict>
</array>
<key>GridInfo</key>
<dict>
<key>GridSpacing</key>
<real>5.6692914962768555</real>
<key>MajorGridSpacing</key>
<integer>10</integer>
<key>ShowsGrid</key>
<string>YES</string>
</dict>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>2</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoLineLength</key>
<real>0.20000000298023224</real>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-01-09 14:26:57 +0000</string>
<key>Modifier</key>
<string>Jakob Schlyter</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>OutlineStyle</key>
<string>Basic</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>12</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>12</string>
</array>
<key>NSOrientation</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwGG</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{842, 595}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>12</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>12</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>AAS</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>3</integer>
<key>UseEntirePage</key>
<true/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>Expanded_Canvases</key>
<array>
<string>Key protection</string>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{30, 45}, {1626, 982}}</string>
<key>ShowInfo</key>
<true/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>230</integer>
<key>TopSlabHeight</key>
<real>363</real>
<key>VisibleRegion</key>
<string>{{0, -29.999999999999993}, {818.00000000000011, 632.77818853974134}}</string>
<key>Zoom</key>
<real>1.3227383863080684</real>
<key>ZoomValues</key>
<array>
<array>
<string>AAS</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>