PyKMIP library version 0.0.1

This implementation supports version 1.1 of the KMIP spec. The
library supports the following operations for SymmetricKey objects:

create
register
get
destroy
This commit is contained in:
Peter Hamilton 2014-08-11 16:34:30 -04:00
parent a0d8c9195e
commit 1cb6deaf0b
68 changed files with 10965 additions and 526 deletions

6
.gitignore vendored
View File

@ -1,3 +1,9 @@
.project
.pydevproject
*.pyc
.coverage
.tox/
ChangeLog
PyKMIP.egg-info/
dist/

2
AUTHORS Normal file
View File

@ -0,0 +1,2 @@
Nathan Reller <Nathan.Reller@jhuapl.edu>
Peter Hamilton <peter.hamilton@jhuapl.edu>

202
LICENSE
View File

@ -1 +1,201 @@
/* FIXME Insert a license here */
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2013, Rackspace (http://www.rackspace.com)
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
http://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.

70
bin/run_server.py Normal file
View File

@ -0,0 +1,70 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
import logging
import optparse
import sys
from thrift.server import TServer
from thrift.transport import TSocket
from thrift.transport import TTransport
from kmip.core.server import KMIPImpl
from kmip.services.kmip_protocol import KMIPProtocolFactory
from kmip.services.kmip_server import Processor
def run_server(host='127.0.0.1', port=5696):
logger = logging.getLogger(__name__)
handler = KMIPImpl()
processor = Processor(handler)
transport = TSocket.TServerSocket(host, port)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = KMIPProtocolFactory()
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
logger.info('Starting the KMIP server')
try:
server.serve()
except KeyboardInterrupt:
logger.info('KeyboardInterrupt received while serving')
except Exception, e:
logger.info('Exception received while serving: {0}'.format(e))
finally:
transport.close()
logger.info('Shutting down KMIP server')
def build_cli_parser():
parser = optparse.OptionParser(usage="%prog [options]",
description="Run KMIP Server")
parser.add_option("-n", "--hostname", action="store", default='127.0.0.1',
dest="hostname",
help="Hostname/IP address of platform running the KMIP "
"server (e.g., localhost, 127.0.0.1)")
parser.add_option("-p", "--port", action="store", default=5696,
dest="port", help="Port number for KMIP services")
return parser
if __name__ == '__main__':
parser = build_cli_parser()
opts, args = parser.parse_args(sys.argv[1:])
run_server(opts.hostname, opts.port)

6
bin/run_server.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
set -eu
python run_server.py

6
bin/run_tests.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
set -eu
tox

1
docs/README Normal file
View File

@ -0,0 +1 @@
PyKMIP documentation goes here.

View File

@ -0,0 +1,57 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
import logging.config
import os
import sys
path = os.path.join(os.path.dirname(__file__), 'logconfig.ini')
if os.path.exists(path):
logging.config.fileConfig(path)
else:
minor_version = sys.version_info[1]
if minor_version == 7:
config = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simpleFormatter': {
'format':
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
}
},
'handlers': {
'consoleHandler': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simpleFormatter',
'stream': sys.stdout
}
},
'loggers': {
'root': {
'level': 'DEBUG',
'handlers': ['consoleHandler']
}
}
}
logging.config.dictConfig(config)
else:
logging.basicConfig()
__all__ = ['test', 'transport']

17
kmip/core/__init__.py Normal file
View File

@ -0,0 +1,17 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
__all__ = ['attributes', 'enums', 'errors', 'messages', 'objects',
'primitives', 'protocol', 'utils']

350
kmip/core/attributes.py Normal file
View File

@ -0,0 +1,350 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
import enums
from kmip.core.enums import Tags
from kmip.core.errors import ErrorStrings
from kmip.core.primitives import Struct
from kmip.core.primitives import Integer
from kmip.core.primitives import Enumeration
from kmip.core.primitives import TextString
from utils import BytearrayStream
# 3.1
class UniqueIdentifier(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.UNIQUE_IDENTIFIER)
# 3.2
class Name(Struct):
class NameValue(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.NAME_VALUE)
class NameType(Enumeration):
ENUM_TYPE = enums.NameType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.NAME_TYPE)
def __init__(self, name_value=None, name_type=None):
super(self.__class__, self).__init__(tag=Tags.NAME)
self.name_value = name_value
self.name_type = name_type
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the value and type of the name
self.name_value = Name.NameValue()
self.name_type = Name.NameType()
self.name_value.read(tstream)
self.name_type.read(tstream)
self.is_oversized(tstream)
def write(self, ostream):
tstream = BytearrayStream()
# Write the value and type of the name
self.name_value.write(tstream)
self.name_type.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
@classmethod
def create(cls, name_value, name_type):
value = cls.NameValue(name_value)
n_type = cls.NameType(name_type)
return Name(name_value=value,
name_type=n_type)
# 3.3
class ObjectType(Enumeration):
ENUM_TYPE = enums.ObjectType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.OBJECT_TYPE)
# 3.4
class CryptographicAlgorithm(Enumeration):
ENUM_TYPE = enums.CryptographicAlgorithm
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CRYPTOGRAPHIC_ALGORITHM)
# 3.5
class CryptographicLength(Integer):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CRYPTOGRAPHIC_LENGTH)
# 3.6
class CryptographicParameters(Struct):
class BlockCipherMode(Enumeration):
ENUM_TYPE = enums.BlockCipherMode
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.BLOCK_CIPHER_MODE)
class PaddingMethod(Enumeration):
ENUM_TYPE = enums.PaddingMethod
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.PADDING_METHOD)
class HashingAlgorithm(Enumeration):
ENUM_TYPE = enums.HashingAlgorithm
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.HASHING_ALGORITHM)
class KeyRoleType(Enumeration):
ENUM_TYPE = enums.KeyRoleType
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.KEY_ROLE_TYPE)
def __init__(self,
block_cipher_mode=None,
padding_method=None,
hashing_algorithm=None,
key_role_type=None):
super(self.__class__, self).__init__(tag=Tags.CRYPTOGRAPHIC_PARAMETERS)
self.block_cipher_mode = block_cipher_mode
self.padding_method = padding_method
self.hashing_algorithm = hashing_algorithm
self.key_role_type = key_role_type
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
if self.is_tag_next(Tags.BLOCK_CIPHER_MODE, tstream):
self.block_cipher_mode = CryptographicParameters.BlockCipherMode()
self.block_cipher_mode.read(tstream)
if self.is_tag_next(Tags.PADDING_METHOD, tstream):
self.padding_method = CryptographicParameters.PaddingMethod()
self.padding_method.read(tstream)
if self.is_tag_next(Tags.HASHING_ALGORITHM, tstream):
self.hashing_algorithm = CryptographicParameters.HashingAlgorithm()
self.hashing_algorithm.read(tstream)
if self.is_tag_next(Tags.KEY_ROLE_TYPE, tstream):
self.key_role_type = CryptographicParameters.KeyRoleType()
self.key_role_type.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the request payload
if self.block_cipher_mode is not None:
self.block_cipher_mode.write(tstream)
if self.padding_method is not None:
self.padding_method.write(tstream)
if self.hashing_algorithm is not None:
self.hashing_algorithm.write(tstream)
if self.key_role_type is not None:
self.key_role_type.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 3.8
class CertificateType(Enumeration):
ENUM_TYPE = enums.CertificateType
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CERTIFICATE_TYPE)
# 3.19
class CryptographicUsageMask(Integer):
ENUM_TYPE = enums.CryptographicUsageMask
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CRYPTOGRAPHIC_USAGE_MASK)
# 3.33
class ObjectGroup(TextString):
def __init__(self, value=None):
super(self.__class__,
self).__init__(value, Tags.OBJECT_GROUP)
# 3.36
class ApplicationSpecificInformation(Struct):
class ApplicationNamespace(TextString):
def __init__(self, value=None):
super(self.__class__,
self).__init__(value, Tags.APPLICATION_NAMESPACE)
class ApplicationData(TextString):
def __init__(self, value=None):
super(self.__class__,
self).__init__(value, Tags.APPLICATION_DATA)
def __init__(self, application_namespace=None,
application_data=None):
super(self.__class__,
self).__init__(Tags.APPLICATION_SPECIFIC_INFORMATION)
self.application_namespace = application_namespace
self.application_data = application_data
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.application_namespace = self.ApplicationNamespace()
self.application_data = self.ApplicationData()
self.application_namespace.read(tstream)
self.application_data.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.application_namespace.write(tstream)
self.application_data.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
name = self.__class__.__name__
msg = ErrorStrings.BAD_EXP_RECV
if self.application_namespace is not None:
if self.application_data is None:
member = 'application_data'
raise ValueError(msg.format('{}.{}'.format(name, member),
'value', 'not None', 'None'))
else:
member = 'application_namespace'
exp_type = self.ApplicationNamespace
if not isinstance(self.application_namespace, exp_type):
rcv_type = type(self.application_namespace)
raise TypeError(msg.format('{}.{}'.format(name, member),
'type', exp_type, rcv_type))
if self.application_data is not None:
if self.application_namespace is None:
member = 'application_namespace'
raise ValueError(msg.format('{}.{}'.format(name, member),
'value', 'not None', 'None'))
else:
member = 'application_data'
exp_type = self.ApplicationData
if not isinstance(self.application_data, exp_type):
rcv_type = type(self.application_data)
raise TypeError(msg.format('{}.{}'.format(name, member),
'type', exp_type, rcv_type))
@classmethod
def create(cls, application_namespace, application_data):
namespace = ApplicationSpecificInformation.\
ApplicationNamespace(application_namespace)
data = ApplicationSpecificInformation.\
ApplicationData(application_data)
return ApplicationSpecificInformation(application_namespace=namespace,
application_data=data)
# 3.37
class ContactInformation(TextString):
def __init__(self, value=None):
super(self.__class__,
self).__init__(value, Tags.CONTACT_INFORMATION)
# 3.39
# TODO (peter-hamilton) A CustomAttribute TextString is not sufficient to
# TODO (peter-hamilton) cover all potential custom attributes. This is a
# TODO (peter-hamilton) temporary stopgap.
class CustomAttribute(TextString):
def __init__(self, value=None):
super(self.__class__,
self).__init__(value, Tags.ATTRIBUTE_VALUE)

561
kmip/core/enums.py Normal file
View File

@ -0,0 +1,561 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
# In case of new content, remove the following line to enable flake8 tests
# flake8: noqa
from enum import Enum
class AttributeType(Enum):
UNIQUE_IDENTIFIER = 'Unique Identifier'
NAME = 'Name'
OBJECT_TYPE = 'Object Type'
CRYPTOGRAPHIC_ALGORITHM = 'Cryptographic Algorithm'
CRYPTOGRAPHIC_LENGTH = 'Cryptographic Length'
CRYPTOGRAPHIC_PARAMETERS = 'Cryptographic Parameters'
CRYPTOGRAPHIC_DOMAIN_PARAMETERS = 'Cryptographic Domain Parameters'
CERTIFICATE_TYPE = 'Certificate Type'
CERTIFICATE_LENGTH = 'Certificate Length'
X_509_CERTIFICATE_IDENTIFIER = 'X.509 Certificate Identifier'
X_509_CERTIFICATE_SUBJECT = 'X.509 Certificate Subject'
X_509_CERTIFICATE_ISSUER = 'X.509 Certificate Issuer'
CERTIFICATE_IDENTIFIER = 'Certificate Identifier'
CERTIFICATE_SUBJECT = 'Certificate Subject'
CERTIFICATE_ISSUER = 'Certificate Issuer'
DIGITAL_SIGNATURE_ALGORITHM = 'Digital Signature Algorithm'
DIGEST = 'Digest'
OPERATION_POLICY_NAME = 'Operation Policy Name'
CRYPTOGRAPHIC_USAGE_MASK = 'Cryptographic Usage Mask'
LEASE_TIME = 'Lease Time'
USAGE_LIMITS = 'Usage Limits'
STATE = 'State'
INITIAL_DATE = 'Initial Date'
ACTIVATION_DATE = 'Activation Date'
PROCESS_START_DATE = 'Process Start Date'
PROTECT_STOP_DATE = 'Protect Stop Date'
DEACTIVATION_DATE = 'Deactivation Date'
DESTROY_DATE = 'Destroy Date'
COMPROMISE_OCCURRENCE_DATE = 'Compromise Occurrence Date'
COMPROMISE_DATE = 'Compromise Date'
REVOCATION_REASON = 'Revocation Reason'
ARCHIVE_DATE = 'Archive Date'
OBJECT_GROUP = 'Object Group'
FRESH = 'Fresh'
LINK = 'Link'
APPLICATION_SPECIFIC_INFORMATION = 'Application Specific Information'
CONTACT_INFORMATION = 'Contact Information'
LAST_CHANGE_DATE = 'Last Change Date'
CUSTOM_ATTRIBUTE = 'Custom Attribute'
# 9.1.1.2
class Types(Enum):
DEFAULT = 0x00
STRUCTURE = 0x01
INTEGER = 0x02
LONG_INTEGER = 0x03
BIG_INTEGER = 0x04
ENUMERATION = 0x05
BOOLEAN = 0x06
TEXT_STRING = 0x07
BYTE_STRING = 0x08
DATE_TIME = 0x09
INTERVAL = 0x0A
# 9.1.3.1
class Tags(Enum):
DEFAULT = 0x420000
ACTIVATION_DATE = 0x420001
APPLICATION_DATA = 0x420002
APPLICATION_NAMESPACE = 0x420003
APPLICATION_SPECIFIC_INFORMATION = 0x420004
ARCHIVE_DATE = 0x420005
ASYNCHRONOUS_CORRELATION_VALUE = 0x420006
ASYNCHRONOUS_INDICATOR = 0x420007
ATTRIBUTE = 0x420008
ATTRIBUTE_INDEX = 0x420009
ATTRIBUTE_NAME = 0x42000A
ATTRIBUTE_VALUE = 0x42000B
AUTHENTICATION = 0x42000C
BATCH_COUNT = 0x42000D
BATCH_ERROR_CONTINUATION_OPTION = 0x42000E
BATCH_ITEM = 0x42000F
BATCH_ORDER_OPTION = 0x420010
BLOCK_CIPHER_MODE = 0x420011
CANCELLATION_RESULT = 0x420012
CERTIFICATE = 0x420013
CERTIFICATE_IDENTIFIER = 0x420014 # DEPRECATED
CERTIFICATE_ISSUER = 0x420015 # DEPRECATED
CERTIFICATE_ISSUER_ALTERNATIVE_NAME = 0x420016 # DEPRECATED
CERTIFICATE_ISSUER_DISTINGUISHED_NAME = 0x420017 # DEPRECATED
CERTIFICATE_REQUEST = 0x420018
CERTIFICATE_REQUEST_TYPE = 0x420019
CERTIFICATE_SUBJECT = 0x42001A # DEPRECATED
CERTIFICATE_SUBJECT_ALTERNATIVE_NAME = 0x42001B # DEPRECATED
CERTIFICATE_SUBJECT_DISTINGUISHED_NAME = 0x42001C # DEPRECATED
CERTIFICATE_TYPE = 0x42001D
CERTIFICATE_VALUE = 0x42001E
COMMON_TEMPLATE_ATTRIBUTE = 0x42001F
COMPROMISE_DATE = 0x420020
COMPROMISE_OCCURRENCE_DATE = 0x420021
CONTACT_INFORMATION = 0x420022
CREDENTIAL = 0x420023
CREDENTIAL_TYPE = 0x420024
CREDENTIAL_VALUE = 0x420025
CRITICALITY_INDICATOR = 0x420026
CRT_COEFFICIENT = 0x420027
CRYPTOGRAPHIC_ALGORITHM = 0x420028
CRYPTOGRAPHIC_DOMAIN_PARAMETERS = 0x420029
CRYPTOGRAPHIC_LENGTH = 0x42002A
CRYPTOGRAPHIC_PARAMETERS = 0x42002B
CRYPTOGRAPHIC_USAGE_MASK = 0x42002C
CUSTOM_ATTRIBUTE = 0x42002D
D = 0x42002E
DEACTIVATION_DATE = 0x42002F
DERIVATION_DATA = 0x420030
DERIVATION_METHOD = 0x420031
DERIVATION_PARAMETERS = 0x420032
DESTROY_DATE = 0x420033
DIGEST = 0x420034
DIGEST_VALUE = 0x420035
ENCRYPTION_KEY_INFORMATION = 0x420036
G = 0x420037
HASHING_ALGORITHM = 0x420038
INITIAL_DATE = 0x420039
INITIALIZATION_VECTOR = 0x42003A
ISSUER = 0x42003B # DEPRECATED
ITERATION_COUNT = 0x42003C
IV_COUNTER_NONCE = 0x42003D
J = 0x42003E
KEY = 0x42003F
KEY_BLOCK = 0x420040
KEY_COMPRESSION_TYPE = 0x420041
KEY_FORMAT_TYPE = 0x420042
KEY_MATERIAL = 0x420043
KEY_PART_IDENTIFIER = 0x420044
KEY_VALUE = 0x420045
KEY_WRAPPING_DATA = 0x420046
KEY_WRAPPING_SPECIFICATION = 0x420047
LAST_CHANGE_DATE = 0x420048
LEASE_TIME = 0x420049
LINK = 0x42004A
LINK_TYPE = 0x42004B
LINKED_OBJECT_IDENTIFIER = 0x42004C
MAC_SIGNATURE = 0x42004D
MAC_SIGNATURE_KEY_INFORMATION = 0x42004E
MAXIMUM_ITEMS = 0x42004F
MAXIMUM_RESPONSE_SIZE = 0x420050
MESSAGE_EXTENSION = 0x420051
MODULUS = 0x420052
NAME = 0x420053
NAME_TYPE = 0x420054
NAME_VALUE = 0x420055
OBJECT_GROUP = 0x420056
OBJECT_TYPE = 0x420057
OFFSET = 0x420058
OPAQUE_DATA_TYPE = 0x420059
OPAQUE_DATA_VALUE = 0x42005A
OPAQUE_OBJECT = 0x42005B
OPERATION = 0x42005C
OPERATION_POLICY_NAME = 0x42005D
P = 0x42005E
PADDING_METHOD = 0x42005F
PRIME_EXPONENT_P = 0x420060
PRIME_EXPONENT_Q = 0x420061
PRIME_FIELD_SIZE = 0x420062
PRIVATE_EXPONENT = 0x420063
PRIVATE_KEY = 0x420064
PRIVATE_KEY_TEMPLATE_ATTRIBUTE = 0x420065
PRIVATE_KEY_UNIQUE_IDENTIFIER = 0x420066
PROCESS_START_DATE = 0x420067
PROTECT_STOP_DATE = 0x420068
PROTOCOL_VERSION = 0x420069
PROTOCOL_VERSION_MAJOR = 0x42006A
PROTOCOL_VERSION_MINOR = 0x42006B
PUBLIC_EXPONENT = 0x42006C
PUBLIC_KEY = 0x42006D
PUBLIC_KEY_TEMPLATE_ATTRIBUTE = 0x42006E
PUBLIC_KEY_UNIQUE_IDENTIFIER = 0x42006F
PUT_FUNCTION = 0x420070
Q = 0x420071
Q_STRING = 0x420072
QLENGTH = 0x420073
QUERY_FUNCTION = 0x420074
RECOMMENDED_CURVE = 0x420075
REPLACED_UNIQUE_IDENTIFIER = 0x420076
REQUEST_BATCH_ITEM = 0x42000F
REQUEST_HEADER = 0x420077
REQUEST_MESSAGE = 0x420078
REQUEST_PAYLOAD = 0x420079
RESPONSE_BATCH_ITEM = 0x42000F
RESPONSE_HEADER = 0x42007A
RESPONSE_MESSAGE = 0x42007B
RESPONSE_PAYLOAD = 0x42007C
RESULT_MESSAGE = 0x42007D
RESULT_REASON = 0x42007E
RESULT_STATUS = 0x42007F
REVOCATION_MESSAGE = 0x420080
REVOCATION_REASON = 0x420081
REVOCATION_REASON_CODE = 0x420082
KEY_ROLE_TYPE = 0x420083
SALT = 0x420084
SECRET_DATA = 0x420085
SECRET_DATA_TYPE = 0x420086
SERIAL_NUMBER = 0x420087 # DEPRECATED
SERVER_INFORMATION = 0x420088
SPLIT_KEY = 0x420089
SPLIT_KEY_METHOD = 0x42008A
SPLIT_KEY_PARTS = 0x42008B
SPLIT_KEY_THRESHOLD = 0x42008C
STATE = 0x42008D
STORAGE_STATUS_MASK = 0x42008E
SYMMETRIC_KEY = 0x42008F
TEMPLATE = 0x420090
TEMPLATE_ATTRIBUTE = 0x420091
TIME_STAMP = 0x420092
UNIQUE_BATCH_ITEM_ID = 0x420093
UNIQUE_IDENTIFIER = 0x420094
USAGE_LIMITS = 0x420095
USAGE_LIMITS_COUNT = 0x420096
USAGE_LIMITS_TOTAL = 0x420097
USAGE_LIMITS_UNIT = 0x420098
USERNAME = 0x420099
VALIDITY_DATE = 0x42009A
VALIDITY_INDICATOR = 0x42009B
VENDOR_EXTENSION = 0x42009C
VENDOR_IDENTIFICATION = 0x42009D
WRAPPING_METHOD = 0x42009E
X = 0x42009F
Y = 0x4200A0
PASSWORD = 0x4200A1
DEVICE_IDENTIFIER = 0x4200A2
ENCODING_OPTION = 0x4200A3
EXTENSION_INFORMATION = 0x4200A4
EXTENSION_NAME = 0x4200A5
EXTENSION_TAG = 0x4200A6
EXTENSION_TYPE = 0x4200A7
FRESH = 0x4200A8
MACHINE_IDENTIFIER = 0x4200A9
MEDIA_IDENTIFIER = 0x4200AA
NETWORK_IDENTIFIER = 0x4200AB
OBJECT_GROUP_MEMBER = 0x4200AC
CERTIFICATE_LENGTH = 0x4200AD
DIGITAL_SIGNATURE_ALGORITHM = 0x4200AE
CERTIFICATE_SERIAL_NUMBER = 0x4200AF
DEVICE_SERIAL_NUMBER = 0x4200B0
ISSUER_ALTERNATIVE_NAME = 0x4200B1
ISSUER_DISTINGUISHED_NAME = 0x4200B2
SUBJECT_ALTERNATIVE_NAME = 0x4200B3
SUBJECT_DISTINGUISHED_NAME = 0x4200B4
X_509_CERTIFICATE_IDENTIFER = 0x4200B5
X_509_CERTIFICATE_ISSUER = 0x4200B6
X_509_CERTIFICATE_SUBJECT = 0x4200B7
# 9.1.3.2.1
class CredentialType(Enum):
USERNAME_AND_PASSWORD = 0x00000001
DEVICE = 0x00000002
# 9.1.3.2.2
class KeyCompressionType(Enum):
EC_PUBLIC_KEY_TYPE_UNCOMPRESSED = 0x00000001
EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_PRIME = 0x00000002
EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_CHAR2 = 0x00000003
EC_PUBLIC_KEY_TYPE_X9_62_HYBRID = 0x00000004
# 9.1.3.2.3
class KeyFormatType(Enum):
RAW = 0x00000001
OPAQUE = 0x00000002
PKCS_1 = 0x00000003
PKCS_8 = 0x00000004
X_509 = 0x00000005
EC_PRIVATE_KEY = 0x00000006
TRANSPARENT_SYMMETRIC_KEY = 0x00000007
TRANSPARENT_DSA_PRIVATE_KEY = 0x00000008
TRANSPARENT_DSA_PUBLIC_KEY = 0x00000009
TRANSPARENT_RSA_PRIVATE_KEY = 0x0000000A
TRANSPARENT_RSA_PUBLIC_KEY = 0x0000000B
TRANSPARENT_DH_PRIVATE_KEY = 0x0000000C
TRANSPARENT_DH_PUBLIC_KEY = 0x0000000D
TRANSPARENT_ECDSA_PRIVATE_KEY = 0x0000000E
TRANSPARENT_ECDSA_PUBLIC_KEY = 0x0000000F
TRANSPARENT_ECDH_PRIVATE_KEY = 0x00000010
TRANSPARENT_ECDH_PUBLIC_KEY = 0x00000011
TRANSPARENT_ECMQV_PRIVATE_KEY = 0x00000012
TRANSPARENT_ECMQV_PUBLIC_KEY = 0x00000013
# 9.1.3.2.4
class WrappingMethod(Enum):
ENCRYPT = 0x00000001
MAC_SIGN = 0x00000002
ENCRYPT_THEN_MAC_SIGN = 0x00000003
MAC_SIGN_THEN_ENCRYPT = 0x00000004
TR_31 = 0x00000005
# 9.1.3.2.6
class CertificateType(Enum):
X_509 = 0x00000001
PGP = 0x00000002
# 9.1.3.2.8
class SplitKeyMethod(Enum):
XOR = 0x00000001
POLYNOMIAL_SHARING_GF = 0x00000002
POLYNOMIAL_SHARING_PRIME_FIELD = 0x00000003
# 9.1.3.2.9
class SecretDataType(Enum):
PASSWORD = 0x00000001
SEED = 0x00000002
# 9.1.3.2.10
class OpaqueDataType(Enum):
pass
# 9.1.3.2.11
class NameType(Enum):
UNINTERPRETED_TEXT_STRING = 0x00000001
URI = 0x00000002
# 9.1.3.2.12
class ObjectType(Enum):
CERTIFICATE = 0x00000001
SYMMETRIC_KEY = 0x00000002
PUBLIC_KEY = 0x00000003
PRIVATE_KEY = 0x00000004
SPLIT_KEY = 0x00000005
TEMPLATE = 0x00000006
SECRET_DATA = 0x00000007
OPAQUE_DATA = 0x00000008
# 9.1.3.2.13
class CryptographicAlgorithm(Enum):
DES = 0x00000001
TRIPLE_DES = 0x00000002 # '3DES' is invalid syntax
AES = 0x00000003
RSA = 0x00000004
DSA = 0x00000005
ECDSA = 0x00000006
HMAC_SHA1 = 0x00000007
HMAC_SHA224 = 0x00000008
HMAC_SHA256 = 0x00000009
HMAC_SHA384 = 0x0000000A
HMAC_SHA512 = 0x0000000B
HMAC_MD5 = 0x0000000C
DH = 0x0000000D
ECDH = 0x0000000E
ECMQV = 0x0000000F
BLOWFISH = 0x00000010
CAMELLIA = 0x00000011
CAST5 = 0x00000012
IDEA = 0x00000013
MARS = 0x00000014
RC2 = 0x00000015
RC4 = 0x00000016
RC5 = 0x00000017
SKIPJACK = 0x00000018
TWOFISH = 0x00000019
# 9.1.3.2.14
class BlockCipherMode(Enum):
CBC = 0x00000001
ECB = 0x00000002
PCBC = 0x00000003
CFB = 0x00000004
OFB = 0x00000005
CTR = 0x00000006
CMAC = 0x00000007
CCM = 0x00000008
GCM = 0x00000009
CBC_MAC = 0x0000000A
XTS = 0x0000000B
AES_KEY_WRAP_PADDING = 0x0000000C
NIST_KEY_WRAP = 0x0000000D
X9_102_AESKW = 0x0000000E
X9_102_TDKW = 0x0000000F
X9_102_AKW1 = 0x00000010
X9_102_AKW2 = 0x00000011
# 9.1.3.2.15
class PaddingMethod(Enum):
NONE = 0x00000001
OAEP = 0x00000002
PKCS5 = 0x00000003
SSL3 = 0x00000004
ZEROS = 0x00000005
ANSI_X9_23 = 0x00000006
ISO_10126 = 0x00000007
PKCS1_V_1_5 = 0x00000008
X9_31 = 0x00000009
PSS = 0x0000000A
# 9.1.3.2.16
class HashingAlgorithm(Enum):
MD2 = 0x00000001
MD4 = 0x00000002
MD5 = 0x00000003
SHA_1 = 0x00000004
SHA_224 = 0x00000005
SHA_256 = 0x00000006
SHA_384 = 0x00000007
SHA_512 = 0x00000008
RIPEMD_160 = 0x00000009
TIGER = 0x0000000A
WHIRLPOOL = 0x0000000B
# 9.1.3.2.17
class KeyRoleType(Enum):
BDK = 0x00000001
CVK = 0x00000002
DEK = 0x00000003
MKAC = 0x00000004
MKSMC = 0x00000005
MKSMI = 0x00000006
MKDAC = 0x00000007
MKDN = 0x00000008
MKCP = 0x00000009
MKOTH = 0x0000000A
KEK = 0x0000000B
MAC_16609 = 0x0000000C
MAC_97971 = 0x0000000D
MAC_97972 = 0x0000000E
MAC_97973 = 0x0000000F
MAC_97974 = 0x00000010
MAC_97975 = 0x00000011
ZPK = 0x00000012
PVKIBM = 0x00000013
PVKPVV = 0x00000014
PVKOTH = 0x00000015
# 9.1.3.2.27
class Operation(Enum):
CREATE = 0x00000001
CREATE_KEY_PAIR = 0x00000002
REGISTER = 0x00000003
REKEY = 0x00000004
DERIVE_KEY = 0x00000005
CERTIFY = 0x00000006
RECERTIFY = 0x00000007
LOCATE = 0x00000008
CHECK = 0x00000009
GET = 0x0000000A
GET_ATTRIBUTES = 0x0000000B
GET_ATTRIBUTE_LIST = 0x0000000C
ADD_ATTRIBUTE = 0x0000000D
MODIFY_ATTRIBUTE = 0x0000000E
DELETE_ATTRIBUTE = 0x0000000F
OBTAIN_LEASE = 0x00000010
GET_USAGE_ALLOCATION = 0x00000011
ACTIVATE = 0x00000012
REVOKE = 0x00000013
DESTROY = 0x00000014
ARCHIVE = 0x00000015
RECOVER = 0x00000016
VALIDATE = 0x00000017
QUERY = 0x00000018
CANCEL = 0x00000019
POLL = 0x0000001A
NOTIFY = 0x0000001B
PUT = 0x0000001C
REKEY_KEY_PAIR = 0x0000001D
DISCOVER_VERSIONS = 0x0000001E
# 9.1.3.2.28
class ResultStatus(Enum):
SUCCESS = 0x00000000
OPERATION_FAILED = 0x00000001
OPERATION_PENDING = 0x00000002
OPERATION_UNDONE = 0x00000003
# 9.1.3.2.29
class ResultReason(Enum):
ITEM_NOT_FOUND = 0x00000001
RESPONSE_TOO_LARGE = 0x00000002
AUTHENTICATION_NOT_SUCCESSFUL = 0x00000003
INVALID_MESSAGE = 0x00000004
OPERATION_NOT_SUPPORTED = 0x00000005
MISSING_DATA = 0x00000006
INVALID_FIELD = 0x00000007
FEATURE_NOT_SUPPORTED = 0x00000008
OPERATION_CANCELED_BY_REQUESTER = 0x00000009
CRYPTOGRAPHIC_FAILURE = 0x0000000A
ILLEGAL_OPERATION = 0x0000000B
PERMISSION_DENIED = 0x0000000C
OBJECT_ARCHIVED = 0x0000000D
INDEX_OUT_OF_BOUNDS = 0x0000000E
APPLICATION_NAMESPACE_NOT_SUPPORTED = 0x0000000F
KEY_FORMAT_TYPE_NOT_SUPPORTED = 0x00000010
KEY_COMPRESSION_TYPE_NOT_SUPPORTED = 0x00000011
ENCODING_OPTION_ERROR = 0x00000012
GENERAL_FAILURE = 0x00000100
# 9.1.3.2.30
class BatchErrorContinuationOption(Enum):
CONTINUE = 0x00000001
STOP = 0x00000002
UNDO = 0x00000003
# 9.1.3.2.32
class EncodingOption(Enum):
NO_ENCODING = 0x00000001
TTLV_ENCODING = 0x00000002
# 9.1.3.3
# 9.1.3.3.1
class CryptographicUsageMask(Enum):
SIGN = 0x00000001
VERIFY = 0x00000002
ENCRYPT = 0x00000004
DECRYPT = 0x00000008
WRAP_KEY = 0x00000010
UNWRAP_KEY = 0x00000020
EXPORT = 0x00000040
MAC_GENERATE = 0x00000080
MAC_VERIFY = 0x00000100
DERIVE_KEY = 0x00000200
CONTENT_COMMITMENT = 0x00000400
KEY_AGREEMENT = 0x00000800
CERTIFICATE_SIGN = 0x00001000
CRL_SIGN = 0x00002000
GENERATE_CRYPTOGRAM = 0x00004000
VALIDATE_CRYPTOGRAM = 0x00008000
TRANSLATE_ENCRYPT = 0x00010000
TRANSLATE_DECRYPT = 0x00020000
TRANSLATE_WRAP = 0x00040000
TRANSLATE_UNWRAP = 0x00080000

130
kmip/core/errors.py Normal file
View File

@ -0,0 +1,130 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
class ErrorStrings:
BAD_EXP_RECV = "Bad {0} {1}: expected {2}, received {3}"
BAD_ENCODING = "Bad {0} {1}: encoding mismatch"
class BaseError(Exception):
"""Base class for exceptions defined in this module."""
def __init__(self, args):
[setattr(self, k, v) for k, v in args.iteritems() if k is not 'self']
class KMIPServerError(BaseError):
"""Base Exception for KMIP server errors."""
def __init__(self, args):
super(KMIPServerError, self).__init__(args)
class KMIPServerZombieError(KMIPServerError):
"""KMIP server error for hung and persistent live KMIP servers."""
def __init__(self, pid):
message = 'KMIP server alive after termination: PID {0}'.format(pid)
super(KMIPServerZombieError, self).__init__({'message': message})
def __str__(self):
return self.message
class KMIPServerSuicideError(KMIPServerError):
"""KMIP server error for prematurely dead KMIP servers."""
def __init__(self, pid):
message = 'KMIP server dead prematurely: PID {0}'.format(pid)
super(KMIPServerSuicideError, self).__init__({'message': message})
def __str__(self):
return self.message
class InitError(BaseError):
"""Exception thrown for bad initializations."""
def __init__(self, cls, exp, recv):
super(InitError, self).__init__(locals())
def __str__(self):
msg = "Tried to initialize {0} instance with bad type: "
msg += "expected {1}, received {2}"
return msg.format(self.cls, self.exp, self.recv)
class WriteValueError(BaseError):
def __init__(self, cls, attr, value):
super(WriteValueError, self).__init__(locals())
def __str__(self):
msg = "Tried to write {0}.{1} with invalid value: {2}"
return msg.format(self.cls, self.attr, self.value)
class WriteTypeError(BaseError):
def __init__(self, cls, attr, value):
super(WriteTypeError, self).__init__(locals())
def __str__(self):
msg = "Tried to write {0}.{1} with invalid type: {2}"
return msg.format(self.cls, self.attr, self.value)
class WriteOverflowError(BaseError):
def __init__(self, cls, attr, exp, recv):
super(WriteOverflowError, self).__init__(locals())
def __str__(self):
msg = "Tried to write {0}.{1} with too many bytes: "
msg += "expected {2}, received {3}"
return msg.format(self.cls, self.attr, self.exp, self.recv)
class ReadValueError(BaseError):
def __init__(self, cls, attr, exp, recv):
super(ReadValueError, self).__init__(locals())
def __str__(self):
msg = "Tried to read {0}.{1}: expected {2}, received {3}"
return msg.format(self.cls, self.attr, self.exp, self.recv)
class InvalidLengthError(ValueError):
def __init__(self, cls, exp, recv):
msg = "Invalid length read for {0}: expected {1}, received {2}"
super(InvalidLengthError, self).__init__(msg.format(cls, exp, recv))
class StreamNotEmptyError(BaseError):
def __init__(self, cls, extra):
super(StreamNotEmptyError, self).__init__(locals())
def __str__(self):
msg = "Invalid length used to read {0}, bytes remaining: {1}"
return msg.format(self.cls, self.extra)
class StateTypeError(TypeError):
def __init__(self, cls, exp, recv):
msg = "Tried to initialize {0} instance with bad type: "
msg += "expected {1}, received {2}"
super(StateTypeError, self).__init__(msg.format(cls, exp, recv))
class StateOverflowError(ValueError):
def __init__(self, cls, attr, exp, recv):
msg = "Tried to write {0}.{1} with too many bytes: "
msg += "expected {2}, received {3}"
super(StateOverflowError, self).__init__(msg.format(cls, attr, exp,
recv))

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,290 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import AttributeType
from kmip.core.attributes import ApplicationSpecificInformation
from kmip.core.attributes import ContactInformation
from kmip.core.attributes import CryptographicAlgorithm
from kmip.core.attributes import CryptographicLength
from kmip.core.attributes import CryptographicUsageMask
from kmip.core.attributes import CustomAttribute
from kmip.core.attributes import Name
from kmip.core.attributes import ObjectGroup
from kmip.core.attributes import UniqueIdentifier
from kmip.core import utils
class AttributeValueFactory(object):
def create_attribute_value(self, name, value):
# Switch on the name of the attribute
if name is AttributeType.UNIQUE_IDENTIFIER:
value = self._create_unique_identifier(value)
elif name is AttributeType.NAME:
value = self._create_name(value)
elif name is AttributeType.OBJECT_TYPE:
value = self._create_object_type(value)
elif name is AttributeType.CRYPTOGRAPHIC_ALGORITHM:
value = self._create_cryptographic_algorithm(value)
elif name is AttributeType.CRYPTOGRAPHIC_LENGTH:
value = self._create_cryptographic_length(value)
elif name is AttributeType.CRYPTOGRAPHIC_PARAMETERS:
value = self._create_cryptographic_parameters(value)
elif name is AttributeType.CRYPTOGRAPHIC_DOMAIN_PARAMETERS:
value = self._create_cryptographic_domain_parameters(value)
elif name is AttributeType.CERTIFICATE_TYPE:
value = self._create_certificate_type(value)
elif name is AttributeType.CERTIFICATE_LENGTH:
value = self._create_certificate_length(value)
elif name is AttributeType.X_509_CERTIFICATE_IDENTIFIER:
value = self._create_x_509_certificate_identifier(value)
elif name is AttributeType.X_509_CERTIFICATE_SUBJECT:
value = self._create_x_509_certificate_subject(value)
elif name is AttributeType.X_509_CERTIFICATE_ISSUER:
value = self._create_x_509_certificate_issuer(value)
elif name is AttributeType.CERTIFICATE_IDENTIFIER:
value = self._create_certificate_identifier(value)
elif name is AttributeType.CERTIFICATE_SUBJECT:
value = self._create_certificate_subject(value)
elif name is AttributeType.CERTIFICATE_ISSUER:
value = self._create_certificate_issuer(value)
elif name is AttributeType.DIGITAL_SIGNATURE_ALGORITHM:
value = self._create_digital_signature_algorithm(value)
elif name is AttributeType.DIGEST:
value = self._create_digest(value)
elif name is AttributeType.OPERATION_POLICY_NAME:
value = self._create_operation_policy_name(value)
elif name is AttributeType.CRYPTOGRAPHIC_USAGE_MASK:
value = self._create_cryptographic_usage_mask(value)
elif name is AttributeType.LEASE_TIME:
value = self._create_lease_time(value)
elif name is AttributeType.USAGE_LIMITS:
value = self._create_usage_limits(value)
elif name is AttributeType.STATE:
value = self._create_state(value)
elif name is AttributeType.INITIAL_DATE:
value = self._create_initial_date(value)
elif name is AttributeType.ACTIVATION_DATE:
value = self._create_activation_date(value)
elif name is AttributeType.PROCESS_START_DATE:
value = self._create_process_start_date(value)
elif name is AttributeType.PROTECT_STOP_DATE:
value = self._create_protect_stop_date(value)
elif name is AttributeType.DEACTIVATION_DATE:
value = self._create_deactivation_date(value)
elif name is AttributeType.DESTROY_DATE:
value = self._create_destroy_date(value)
elif name is AttributeType.COMPROMISE_OCCURRENCE_DATE:
value = self._create_compromise_occurrence_date(value)
elif name is AttributeType.COMPROMISE_DATE:
value = self._create_compromise_date(value)
elif name is AttributeType.REVOCATION_REASON:
value = self._create_revocation_reason(value)
elif name is AttributeType.ARCHIVE_DATE:
value = self._create_archive_date(value)
elif name is AttributeType.OBJECT_GROUP:
value = self._create_object_group(value)
elif name is AttributeType.FRESH:
value = self._create_fresh(value)
elif name is AttributeType.LINK:
value = self._create_link(value)
elif name is AttributeType.APPLICATION_SPECIFIC_INFORMATION:
value = self._create_application_specific_information(value)
elif name is AttributeType.CONTACT_INFORMATION:
value = self._create_contact_information(value)
elif name is AttributeType.LAST_CHANGE_DATE:
value = self._create_last_change_date(value)
elif name is AttributeType.CUSTOM_ATTRIBUTE:
value = self._create_custom_attribute(value)
else:
if not isinstance(name, str):
raise ValueError('Unrecognized attribute type: '
'{}'.format(name))
elif name.startswith('x-'):
# Custom attribute indicated
value = self._create_custom_attribute(value)
return value
def _create_unique_identifier(self, uuid):
return UniqueIdentifier(uuid)
def _create_name(self, name):
if name is not None:
name_value = name.get('name_value')
name_type = name.get('name_type')
return Name.create(name_value, name_type)
else:
return Name()
def _create_object_type(self, obj):
raise NotImplementedError()
def _create_cryptographic_algorithm(self, alg):
return CryptographicAlgorithm(alg)
def _create_cryptographic_length(self, length):
if length is not None and not isinstance(length, int):
msg = utils.build_er_error(CryptographicLength,
'constructor argument type', int,
type(length))
raise TypeError(msg)
return CryptographicLength(length)
def _create_cryptographic_parameters(self, params):
raise NotImplementedError()
def _create_cryptographic_domain_parameters(self, params):
raise NotImplementedError()
def _create_certificate_type(self, cert):
raise NotImplementedError()
def _create_certificate_length(self, length):
raise NotImplementedError()
def _create_x_509_certificate_identifier(self, ident):
raise NotImplementedError()
def _create_x_509_certificate_subject(self, subject):
raise NotImplementedError()
def _create_x_509_certificate_issuer(self, issuer):
raise NotImplementedError()
def _create_certificate_identifier(self, ident):
raise NotImplementedError()
def _create_certificate_subject(self, subject):
raise NotImplementedError()
def _create_certificate_issuer(self, issuer):
raise NotImplementedError()
def _create_digital_signature_algorithm(self, alg):
raise NotImplementedError()
def _create_digest(self, digest):
raise NotImplementedError()
def _create_operation_policy_name(self, name):
raise NotImplementedError()
def _create_cryptographic_usage_mask(self, flags):
mask = None
if flags is not None:
mask = 0
for flag in flags:
mask |= flag.value
return CryptographicUsageMask(mask)
def _create_lease_time(self, lease):
raise NotImplementedError()
def _create_usage_limits(self, limits):
raise NotImplementedError()
def _create_state(self, state):
raise NotImplementedError()
def _create_initial_date(self, date):
raise NotImplementedError()
def _create_activation_date(self, date):
raise NotImplementedError()
def _create_process_start_date(self, date):
raise NotImplementedError()
def _create_protect_stop_date(self, date):
raise NotImplementedError()
def _create_deactivation_date(self, date):
raise NotImplementedError()
def _create_destroy_date(self, date):
raise NotImplementedError()
def _create_compromise_occurrence_date(self, date):
raise NotImplementedError()
def _create_compromise_date(self, date):
raise NotImplementedError()
def _create_revocation_reason(self, reason):
raise NotImplementedError()
def _create_archive_date(self, date):
raise NotImplementedError()
def _create_object_group(self, group):
if group is not None and not isinstance(group, str):
msg = utils.build_er_error(ObjectGroup,
'constructor argument type', str,
type(group))
raise TypeError(msg)
return ObjectGroup(group)
def _create_fresh(self, fresh):
raise NotImplementedError()
def _create_link(self, link):
raise NotImplementedError()
def _create_application_specific_information(self, info):
if info is None:
return ApplicationSpecificInformation()
else:
application_namespace = info.get('application_namespace')
application_data = info.get('application_data')
if not isinstance(application_namespace, str):
msg = utils.build_er_error(ApplicationSpecificInformation,
'constructor argument type',
str, type(application_namespace))
raise TypeError(msg)
if not isinstance(application_data, str):
msg = utils.build_er_error(ApplicationSpecificInformation,
'constructor argument type',
str, type(application_data))
raise TypeError(msg)
return ApplicationSpecificInformation.create(application_namespace,
application_data)
def _create_contact_information(self, info):
if info is None:
return ContactInformation()
else:
if not isinstance(info, str):
msg = utils.build_er_error(ContactInformation,
'constructor argument type', str,
type(info))
raise TypeError(msg)
return ContactInformation(info)
def _create_last_change_date(self, date):
raise NotImplementedError()
def _create_custom_attribute(self, data):
return CustomAttribute(data)

View File

@ -0,0 +1,56 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from enum import Enum
from kmip.core.factories.attribute_values import AttributeValueFactory
from kmip.core.objects import Attribute
from kmip.core import utils
class AttributeFactory(object):
def __init__(self):
self.value_factory = AttributeValueFactory()
def _create_attribute(self, name, value, index):
attribute_name = Attribute.AttributeName(name)
if index is None:
return Attribute(attribute_name=attribute_name,
attribute_value=value)
else:
attribute_index = Attribute.AttributeIndex(index)
return Attribute(attribute_name=attribute_name,
attribute_index=attribute_index,
attribute_value=value)
def create_attribute(self, name, value, index=None):
value = self.value_factory.create_attribute_value(name, value)
if isinstance(name, Enum):
name = name.value
elif isinstance(name, str):
# Name is already a string, pass
pass
else:
msg = utils.build_er_error(Attribute, 'name',
'{} or {}'.format('Enum', 'str'),
type(name))
raise TypeError(msg)
return self._create_attribute(name, value, index)

View File

@ -0,0 +1,72 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import CredentialType
from kmip.core.objects import Credential
class CredentialFactory(object):
def __init__(self):
pass
def _create_credential(self, credential_type, credential_value):
credential_type = Credential.CredentialType(credential_type)
return Credential(credential_type=credential_type,
credential_value=credential_value)
def create_credential(self, cred_type, value):
# Switch on the type of the credential
if cred_type is CredentialType.USERNAME_AND_PASSWORD:
value = self._create_username_password_credential(value)
elif cred_type is CredentialType.DEVICE:
value = self._create_device_credential(value)
else:
msg = 'Unrecognized credential type: {}'
raise ValueError(msg.format(cred_type))
return self._create_credential(cred_type, value)
def _create_username_password_credential(self, value):
username = value.get('Username')
password = value.get('Password')
username = Credential.UsernamePasswordCredential.Username(username)
password = Credential.UsernamePasswordCredential.Password(password)
return Credential.UsernamePasswordCredential(username=username,
password=password)
def _create_device_credential(self, value):
dsn = value.get('Device Serial Number')
password = value.get('Password')
dev_id = value.get('Device Identifier')
net_id = value.get('Network Identifier')
mach_id = value.get('Machine Identifier')
med_id = value.get('Media Identifier')
dsn = Credential.DeviceCredential.DeviceSerialNumber(dsn)
password = Credential.DeviceCredential.Password(password)
dev_id = Credential.DeviceCredential.DeviceIdentifier(dev_id)
net_id = Credential.DeviceCredential.NetworkIdentifier(net_id)
mach_id = Credential.DeviceCredential.MachineIdentifier(mach_id)
med_id = Credential.DeviceCredential.MediaIdentifier(med_id)
return Credential.DeviceCredential(device_serial_number=dsn,
password=password,
device_identifier=dev_id,
network_identifier=net_id,
machine_identifier=mach_id,
media_identifier=med_id)

126
kmip/core/factories/keys.py Normal file
View File

@ -0,0 +1,126 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import KeyFormatType
from kmip.core.keys import RawKey
class KeyFactory(object):
def create_key(self, key_format, value=None):
if value is None:
value = {}
# Switch on the format type of the key
if key_format is KeyFormatType.RAW:
return self._create_raw_key(value)
elif key_format is KeyFormatType.OPAQUE:
return self._create_opaque_key(value)
elif key_format is KeyFormatType.PKCS_1:
return self._create_pkcs_1_key(value)
elif key_format is KeyFormatType.PKCS_8:
return self._create_pkcs_8_key(value)
elif key_format is KeyFormatType.X_509:
return self._create_x_509_key(value)
elif key_format is KeyFormatType.EC_PRIVATE_KEY:
return self._create_ec_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_SYMMETRIC_KEY:
return self._create_transparent_symmetric_key(value)
elif key_format is KeyFormatType.TRANSPARENT_DSA_PRIVATE_KEY:
return self._create_transparent_dsa_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_DSA_PUBLIC_KEY:
return self._create_transparent_dsa_public_key(value)
elif key_format is KeyFormatType.TRANSPARENT_RSA_PRIVATE_KEY:
return self._create_transparent_rsa_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_RSA_PUBLIC_KEY:
return self._create_transparent_rsa_public_key(value)
elif key_format is KeyFormatType.TRANSPARENT_DH_PRIVATE_KEY:
return self._create_transparent_dh_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_DH_PUBLIC_KEY:
return self._create_transparent_dh_public_key(value)
elif key_format is KeyFormatType.TRANSPARENT_ECDSA_PRIVATE_KEY:
return self._create_transparent_ecdsa_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_ECDSA_PUBLIC_KEY:
return self._create_transparent_ecdsa_public_key(value)
elif key_format is KeyFormatType.TRANSPARENT_ECDH_PRIVATE_KEY:
return self._create_transparent_ecdh_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_ECDH_PUBLIC_KEY:
return self._create_transparent_ecdh_public_key(value)
elif key_format is KeyFormatType.TRANSPARENT_ECMQV_PRIVATE_KEY:
return self._create_transparent_ecmqv_private_key(value)
elif key_format is KeyFormatType.TRANSPARENT_ECMQV_PUBLIC_KEY:
return self._create_transparent_ecmqv_public_key(value)
else:
msg = 'Unrecognized key format type: {}'
raise ValueError(msg.format(key_format))
def _create_raw_key(self, value):
data = value.get('bytes')
return RawKey(data)
def _create_opaque_key(self, value):
raise NotImplementedError()
def _create_pkcs_1_key(self, value):
raise NotImplementedError()
def _create_pkcs_8_key(self, value):
raise NotImplementedError()
def _create_x_509_key(self, value):
raise NotImplementedError()
def _create_ec_private_key(self, value):
raise NotImplementedError()
def _create_transparent_symmetric_key(self, value):
raise NotImplementedError()
def _create_transparent_dsa_private_key(self, value):
raise NotImplementedError()
def _create_transparent_dsa_public_key(self, value):
raise NotImplementedError()
def _create_transparent_rsa_private_key(self, value):
raise NotImplementedError()
def _create_transparent_rsa_public_key(self, value):
raise NotImplementedError()
def _create_transparent_dh_private_key(self, value):
raise NotImplementedError()
def _create_transparent_dh_public_key(self, value):
raise NotImplementedError()
def _create_transparent_ecdsa_private_key(self, value):
raise NotImplementedError()
def _create_transparent_ecdsa_public_key(self, value):
raise NotImplementedError()
def _create_transparent_ecdh_private_key(self, value):
raise NotImplementedError()
def _create_transparent_ecdh_public_key(self, value):
raise NotImplementedError()
def _create_transparent_ecmqv_private_key(self, value):
raise NotImplementedError()
def _create_transparent_ecmqv_public_key(self, value):
raise NotImplementedError()

View File

@ -0,0 +1,140 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.factories.keys import KeyFactory
from kmip.core.attributes import CryptographicAlgorithm
from kmip.core.attributes import CryptographicLength
from kmip.core.enums import ObjectType
from kmip.core.errors import ErrorStrings
from kmip.core.objects import Attribute
from kmip.core.objects import KeyBlock
from kmip.core.objects import KeyWrappingData
from kmip.core.objects import KeyValueStruct
from kmip.core.objects import KeyValue
from kmip.core.secrets import SymmetricKey
from kmip.core.secrets import Template
from kmip.core import utils
class SecretFactory(object):
def __init__(self):
self.key_factory = KeyFactory()
self.base_error = ErrorStrings.BAD_EXP_RECV
self.template_input = self.base_error.format('Template', '{0}', '{1}',
'{2}')
def create_secret(self, secret_type, value=None):
if secret_type is ObjectType.CERTIFICATE:
return self._create_certificate(value)
elif secret_type is ObjectType.SYMMETRIC_KEY:
return self._create_symmetric_key(value)
elif secret_type is ObjectType.PUBLIC_KEY:
return self._create_public_key(value)
elif secret_type is ObjectType.PRIVATE_KEY:
return self._create_private_key(value)
elif secret_type is ObjectType.SPLIT_KEY:
return self._create_split_key(value)
elif secret_type is ObjectType.TEMPLATE:
return self._create_template(value)
elif secret_type is ObjectType.SECRET_DATA:
return self._create_secret_data(value)
elif secret_type is ObjectType.OPAQUE_DATA:
return self._create_opaque_data(value)
def _create_certificate(self, value):
raise NotImplementedError()
def _create_symmetric_key(self, value):
if value is None:
return SymmetricKey()
else:
key_type = value.get('key_format_type')
key_compression_type = value.get('key_compression_type')
key_value = value.get('key_value')
cryptographic_algorithm = value.get('cryptographic_algorithm')
cryptographic_length = value.get('cryptographic_length')
key_wrapping_data = value.get('key_wrapping_data')
key_format_type = KeyBlock.KeyFormatType(key_type)
key_comp_type = None
if key_compression_type is not None:
key_comp_type = KeyBlock.KeyCompressionType(
key_compression_type)
key_material = self.key_factory.create_key(key_type,
key_value)
key_val_struc = KeyValueStruct(key_format_type=key_format_type,
key_material=key_material)
key_value = KeyValue(key_value=key_val_struc,
key_format_type=key_format_type)
crypto_algorithm = CryptographicAlgorithm(cryptographic_algorithm)
crypto_length = CryptographicLength(cryptographic_length)
key_wrap_data = None
if key_wrapping_data is not None:
# TODO (peter-hamilton) This currently isn't used in the tests
# TODO (peter-hamilton) but needs to be updated to properly
# TODO (peter-hamilton) create a KeyWrappingData object.
key_wrap_data = KeyWrappingData(key_wrapping_data)
key_block = KeyBlock(key_format_type,
key_comp_type,
key_value,
crypto_algorithm,
crypto_length,
key_wrap_data)
return SymmetricKey(key_block)
def _create_public_key(self, value):
raise NotImplementedError()
def _create_private_key(self, value):
raise NotImplementedError()
def _create_split_key(self, value):
raise NotImplementedError()
def _create_template(self, value):
if value is None:
return Template()
else:
if not isinstance(value, list):
msg = utils.build_er_error(Template,
'constructor argument type', list,
type(value))
raise TypeError(msg)
else:
for val in value:
if not isinstance(val, Attribute):
msg = utils.build_er_error(Template,
'constructor argument type',
Attribute, type(val))
raise TypeError(msg)
return Template(value)
def _create_secret_data(self, value):
raise NotImplementedError()
def _create_opaque_data(self, value):
raise NotImplementedError()

102
kmip/core/keys.py Normal file
View File

@ -0,0 +1,102 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
# This module defines classes representing all of the different key types
# used by KMIP, including the more detailed structures of the Transparent
# Keys defined in Section 2.1.7.
from kmip.core.enums import Tags
from kmip.core.primitives import Struct
from kmip.core.primitives import ByteString
from kmip.core.utils import BytearrayStream
class RawKey(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
class OpaqueKey(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
class PKCS1Key(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
class PKCS8Key(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
class X509Key(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
class ECPrivateKey(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
# 2.1.7.1
class TransparentSymmetricKey(Struct):
class Key(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY)
def __init__(self, key=None):
super(self.__class__, self).__init__(Tags.KEY_MATERIAL)
self.key = key
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.key = TransparentSymmetricKey.Key()
self.key.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.key.write(tstream)
# Write the length and value of the key wrapping data
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass

2
kmip/core/messages/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/test_in.txt
/test_out.txt

View File

@ -0,0 +1,16 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
__all__ = ['contents', 'messages', 'operations']

View File

@ -0,0 +1,224 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core import enums
from kmip.core import objects
from kmip.core import utils
from kmip.core.primitives import Struct
from kmip.core.primitives import Integer
from kmip.core.primitives import Enumeration
from kmip.core.primitives import Boolean
from kmip.core.primitives import TextString
from kmip.core.primitives import ByteString
from kmip.core.primitives import DateTime
# 6.1
class ProtocolVersion(Struct):
class ProtocolVersionMajor(Integer):
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.PROTOCOL_VERSION_MAJOR)
class ProtocolVersionMinor(Integer):
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.PROTOCOL_VERSION_MINOR)
def __init__(self,
protocol_version_major=None,
protocol_version_minor=None):
super(self.__class__, self).__init__(tag=enums.Tags.PROTOCOL_VERSION)
self.protocol_version_major = protocol_version_major
self.protocol_version_minor = protocol_version_minor
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = utils.BytearrayStream(istream.read(self.length))
# Read the major and minor portions of the version number
self.protocol_version_major = ProtocolVersion.ProtocolVersionMajor()
self.protocol_version_minor = ProtocolVersion.ProtocolVersionMinor()
self.protocol_version_major.read(tstream)
self.protocol_version_minor.read(tstream)
self.is_oversized(tstream)
def write(self, ostream):
tstream = utils.BytearrayStream()
# Write the major and minor portions of the protocol version
self.protocol_version_major.write(tstream)
self.protocol_version_minor.write(tstream)
# Write the length and value of the protocol version
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
@classmethod
def create(cls, major, minor):
major_version = cls.ProtocolVersionMajor(major)
minor_version = cls.ProtocolVersionMinor(minor)
return ProtocolVersion(major_version, minor_version)
# 6.2
class Operation(Enumeration):
ENUM_TYPE = enums.Operation
def __init__(self, value=None):
super(self.__class__, self).__init__(value, enums.Tags.OPERATION)
# 6.3
class MaximumResponseSize(Integer):
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.MAXIMUM_RESPONSE_SIZE)
# 6.4
class UniqueBatchItemID(ByteString):
def __init__(self, value=None):
super(self.__class__, self)\
.__init__(value, enums.Tags.UNIQUE_BATCH_ITEM_ID)
# 6.5
class TimeStamp(DateTime):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, enums.Tags.TIME_STAMP)
# 6.6
class Authentication(Struct):
def __init__(self, credential=None):
super(self.__class__, self).__init__(tag=enums.Tags.AUTHENTICATION)
self.credential = credential
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = utils.BytearrayStream(istream.read(self.length))
# Read the credential
self.credential = objects.Credential()
self.credential.read(tstream)
self.is_oversized(tstream)
def write(self, ostream):
tstream = utils.BytearrayStream()
# Write the credential
self.credential.write(tstream)
# Write the length and value of the protocol version
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 6.7
class AsynchronousIndicator(Boolean):
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.ASYNCHRONOUS_INDICATOR)
# 6.8
class AsynchronousCorrelationValue(ByteString):
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.ASYNCHRONOUS_CORRELATION_VALUE)
# 6.9
class ResultStatus(Enumeration):
ENUM_TYPE = enums.ResultStatus
def __init__(self, value=None):
super(self.__class__, self).__init__(value, enums.Tags.RESULT_STATUS)
# 6.10
class ResultReason(Enumeration):
ENUM_TYPE = enums.ResultReason
def __init__(self, value=None):
super(self.__class__, self).__init__(value, enums.Tags.RESULT_REASON)
# 6.11
class ResultMessage(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, enums.Tags.RESULT_MESSAGE)
# 6.12
class BatchOrderOption(Boolean):
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.BATCH_ORDER_OPTION)
# 6.13
class BatchErrorContinuationOption(Enumeration):
ENUM_TYPE = enums.BatchErrorContinuationOption
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.BATCH_ERROR_CONTINUATION_OPTION)
# 6.14
class BatchCount(Integer):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, enums.Tags.BATCH_COUNT)
# 6.16
class MessageExtension(Struct):
def __init__(self):
super(self.__class__, self).__init__(tag=enums.Tags.MESSAGE_EXTENSION)
# 9.1.3.2.2
class KeyCompressionType(Enumeration):
ENUM_TYPE = enums.KeyCompressionType
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.KEY_COMPRESSION_TYPE)
# 9.1.3.2.3
class KeyFormatType(Enumeration):
ENUM_TYPE = enums.KeyFormatType
def __init__(self, value=None):
super(self.__class__, self).\
__init__(value, enums.Tags.KEY_FORMAT_TYPE)

View File

@ -0,0 +1,397 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import Tags
from kmip.core.messages import contents
from kmip.core.messages.contents import AsynchronousCorrelationValue
from kmip.core.messages.contents import BatchErrorContinuationOption
from kmip.core.messages import operations
from kmip.core.primitives import Struct
from kmip.core.utils import BytearrayStream
class RequestHeader(Struct):
def __init__(self,
protocol_version=None,
maximum_response_size=None,
asynchronous_indicator=None,
authentication=None,
batch_error_cont_option=None,
batch_order_option=None,
time_stamp=None,
batch_count=None):
super(self.__class__, self).__init__(tag=Tags.REQUEST_HEADER)
self.protocol_version = protocol_version
self.maximum_response_size = maximum_response_size
self.asynchronous_indicator = asynchronous_indicator
self.authentication = authentication
self.batch_error_cont_option = batch_error_cont_option
self.batch_order_option = batch_order_option
self.time_stamp = time_stamp
self.batch_count = batch_count
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.protocol_version = contents.ProtocolVersion()
self.protocol_version.read(tstream)
# Read the maximum response size if it is present
if self.is_tag_next(Tags.MAXIMUM_RESPONSE_SIZE, tstream):
self.maximum_response_size = contents.MaximumResponseSize()
self.maximum_response_size.read(tstream)
# Read the asynchronous indicator if it is present
if self.is_tag_next(Tags.ASYNCHRONOUS_INDICATOR, tstream):
self.asynchronous_indicator = contents.AsynchronousIndicator()
self.asynchronous_indicator.read(tstream)
# Read the authentication if it is present
if self.is_tag_next(Tags.AUTHENTICATION, tstream):
self.authentication = contents.Authentication()
self.authentication.read(tstream)
# Read the batch error continuation option if it is present
if self.is_tag_next(Tags.BATCH_ERROR_CONTINUATION_OPTION, tstream):
self.batch_error_cont_option = BatchErrorContinuationOption()
self.batch_error_cont_option.read(tstream)
# Read the batch order option if it is present
if self.is_tag_next(Tags.BATCH_ORDER_OPTION, tstream):
self.batch_order_option = contents.BatchOrderOption()
self.batch_order_option.read(tstream)
# Read the time stamp if it is present
if self.is_tag_next(Tags.TIME_STAMP, tstream):
self.time_stamp = contents.TimeStamp()
self.time_stamp.read(tstream)
self.batch_count = contents.BatchCount()
self.batch_count.read(tstream)
self.is_oversized(tstream)
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of a request header to the stream
self.protocol_version.write(tstream)
if self.maximum_response_size is not None:
self.maximum_response_size.write(tstream)
if self.asynchronous_indicator is not None:
self.asynchronous_indicator.write(tstream)
if self.authentication is not None:
self.authentication.write(tstream)
if self.batch_error_cont_option is not None:
self.batch_error_cont_option.write(tstream)
if self.batch_order_option is not None:
self.batch_order_option.write(tstream)
if self.time_stamp is not None:
self.time_stamp.write(tstream)
self.batch_count.write(tstream)
# Write the length and value of the request header
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
class ResponseHeader(Struct):
def __init__(self,
protocol_version=None,
time_stamp=None,
batch_count=None):
super(self.__class__, self).__init__(tag=Tags.RESPONSE_HEADER)
self.protocol_version = protocol_version
self.time_stamp = time_stamp
self.batch_count = batch_count
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.protocol_version = contents.ProtocolVersion()
self.protocol_version.read(tstream)
self.time_stamp = contents.TimeStamp()
self.time_stamp.read(tstream)
self.batch_count = contents.BatchCount()
self.batch_count.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of a response header to the stream
self.protocol_version.write(tstream)
self.time_stamp.write(tstream)
self.batch_count.write(tstream)
# Write the length and value of the request header
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
if self.protocol_version is not None:
# TODO (peter-hamilton) conduct type check
self.protocol_version.validate()
if self.time_stamp is not None:
# TODO (peter-hamilton) conduct type check
self.time_stamp.validate()
if self.batch_count is not None:
# TODO (peter-hamilton) conduct type check
self.batch_count.validate()
class RequestBatchItem(Struct):
def __init__(self,
operation=None,
unique_batch_item_id=None,
request_payload=None,
message_extension=None):
super(self.__class__, self).__init__(tag=Tags.REQUEST_BATCH_ITEM)
self.operation = operation
self.unique_batch_item_id = unique_batch_item_id
self.request_payload = request_payload
self.message_extension = message_extension
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the batch item operation
self.operation = contents.Operation()
self.operation.read(tstream)
# Read the unique batch item ID if it is present
if self.is_tag_next(Tags.UNIQUE_BATCH_ITEM_ID, tstream):
self.unique_batch_item_id = contents.UniqueBatchItemID()
self.unique_batch_item_id.read(tstream)
# Lookup the response payload class that belongs to the operation
cls = operations.REQUEST_MAP.get(self.operation.enum)
self.request_payload = cls()
self.request_payload.read(tstream)
# Read the message extension if it is present
if self.is_tag_next(Tags.MESSAGE_EXTENSION, tstream):
self.message_extension = contents.MessageExtension()
self.message_extension.read(tstream)
self.is_oversized(tstream)
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the batch item to the stream
self.operation.write(tstream)
if self.unique_batch_item_id is not None:
self.unique_batch_item_id.write(tstream)
self.request_payload.write(tstream)
if self.message_extension is not None:
self.message_extension.write(tstream)
# Write the length and value of the batch item
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
class ResponseBatchItem(Struct):
def __init__(self,
operation=None,
unique_batch_item_id=None,
result_status=None,
result_reason=None,
result_message=None,
async_correlation_value=None,
response_payload=None,
message_extension=None):
super(self.__class__, self).__init__(tag=Tags.RESPONSE_BATCH_ITEM)
self.operation = operation
self.unique_batch_item_id = unique_batch_item_id
self.result_status = result_status
self.result_reason = result_reason
self.result_message = result_message
self.async_correlation_value = async_correlation_value
self.response_payload = response_payload
self.message_extension = message_extension
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the batch item operation if it is present
if self.is_tag_next(Tags.OPERATION, tstream):
self.operation = contents.Operation()
self.operation.read(tstream)
# Read the unique batch item ID if it is present
if self.is_tag_next(Tags.UNIQUE_BATCH_ITEM_ID, tstream):
self.unique_batch_item_id = contents.UniqueBatchItemID()
self.unique_batch_item_id.read(tstream)
# Read the batch item result status
self.result_status = contents.ResultStatus()
self.result_status.read(tstream)
# Read the batch item result reason if it is present
if self.is_tag_next(Tags.RESULT_REASON, tstream):
self.result_reason = contents.ResultReason()
self.result_reason.read(tstream)
# Read the batch item result message if it is present
if self.is_tag_next(Tags.RESULT_MESSAGE, tstream):
self.result_message = contents.ResultMessage()
self.result_message.read(tstream)
# Read the batch item asynchronous correlation value if it is present
if self.is_tag_next(Tags.ASYNCHRONOUS_CORRELATION_VALUE, tstream):
self.async_correlation_value = AsynchronousCorrelationValue()
self.async_correlation_value.read(tstream)
# Lookup the response payload class that belongs to the operation
cls = operations.RESPONSE_MAP.get(self.operation.enum)
expected = cls()
if self.is_tag_next(expected.tag, tstream):
self.response_payload = cls()
self.response_payload.read(tstream)
# Read the message extension if it is present
if self.is_tag_next(Tags.MESSAGE_EXTENSION, tstream):
self.message_extension = contents.MessageExtension()
self.message_extension.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the batch item to the stream
if self.operation is not None:
self.operation.write(tstream)
if self.unique_batch_item_id is not None:
self.unique_batch_item_id.write(tstream)
self.result_status.write(tstream)
if self.result_reason is not None:
self.result_reason.write(tstream)
if self.result_message is not None:
self.result_message.write(tstream)
if self.async_correlation_value is not None:
self.async_correlation_value.write(tstream)
if self.response_payload is not None:
self.response_payload.write(tstream)
if self.message_extension is not None:
self.message_extension.write(tstream)
# Write the length and value of the batch item
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
pass
class RequestMessage(Struct):
def __init__(self, request_header=None, batch_items=None,):
super(self.__class__, self).__init__(tag=Tags.REQUEST_MESSAGE)
self.request_header = request_header
self.batch_items = batch_items
def read(self, istream):
super(self.__class__, self).read(istream)
self.request_header = RequestHeader()
self.request_header.read(istream)
self.batch_items = []
for _ in xrange(self.request_header.batch_count.value):
batch_item = RequestBatchItem()
batch_item.read(istream)
self.batch_items.append(batch_item)
def write(self, ostream):
tstream = BytearrayStream()
# Write the request header and all batch items
self.request_header.write(tstream)
for batch_item in self.batch_items:
batch_item.write(tstream)
# Write the TTLV encoding of the request message
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
class ResponseMessage(Struct):
def __init__(self, response_header=None, batch_items=None,):
super(self.__class__, self).__init__(tag=Tags.RESPONSE_MESSAGE)
self.response_header = response_header
self.batch_items = batch_items
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
self.response_header = ResponseHeader()
self.response_header.read(istream)
self.batch_items = []
for _ in xrange(self.response_header.batch_count.value):
batch_item = ResponseBatchItem()
batch_item.read(istream)
self.batch_items.append(batch_item)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the request header and all batch items
self.response_header.write(tstream)
for batch_item in self.batch_items:
batch_item.write(tstream)
# Write the TTLV encoding of the request message
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
pass

View File

@ -0,0 +1,439 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.factories.secrets import SecretFactory
from kmip.core import attributes
from kmip.core import enums
from kmip.core.enums import Tags
from kmip.core.objects import KeyWrappingSpecification
from kmip.core.objects import TemplateAttribute
from kmip.core.primitives import Struct
from kmip.core.primitives import Enumeration
from kmip.core.utils import BytearrayStream
# 4.1
class CreateRequestPayload(Struct):
def __init__(self,
object_type=None,
template_attribute=None):
super(self.__class__, self).__init__(tag=enums.Tags.REQUEST_PAYLOAD)
self.object_type = object_type
self.template_attribute = template_attribute
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.object_type = attributes.ObjectType()
self.template_attribute = TemplateAttribute()
self.object_type.read(tstream)
self.template_attribute.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the object type and template attribute of the request payload
self.object_type.write(tstream)
self.template_attribute.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class CreateResponsePayload(Struct):
def __init__(self,
object_type=None,
unique_identifier=None,
template_attribute=None):
super(self.__class__, self).__init__(tag=enums.Tags.RESPONSE_PAYLOAD)
self.object_type = object_type
self.unique_identifier = unique_identifier
self.template_attribute = template_attribute
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.object_type = attributes.ObjectType()
self.unique_identifier = attributes.UniqueIdentifier()
self.object_type.read(tstream)
self.unique_identifier.read(tstream)
if self.is_tag_next(Tags.TEMPLATE_ATTRIBUTE, tstream):
self.template_attribute = TemplateAttribute()
self.template_attribute.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the request payload
self.object_type.write(tstream)
self.unique_identifier.write(tstream)
if self.template_attribute is not None:
self.template_attribute.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 4.3
class RegisterRequestPayload(Struct):
def __init__(self,
object_type=None,
template_attribute=None,
secret=None):
super(self.__class__, self).__init__(Tags.REQUEST_PAYLOAD)
self.secret_factory = SecretFactory()
self.object_type = object_type
self.template_attribute = template_attribute
self.secret = secret
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.object_type = attributes.ObjectType()
self.template_attribute = TemplateAttribute()
self.object_type.read(tstream)
self.template_attribute.read(tstream)
secret_type = self.object_type.enum
secret = self.secret_factory.create_secret(secret_type)
if self.is_tag_next(secret.tag, tstream):
self.secret = secret
self.secret.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the request payload
self.object_type.write(tstream)
self.template_attribute.write(tstream)
if self.secret is not None:
self.secret.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class RegisterResponsePayload(Struct):
def __init__(self,
unique_identifier=None,
template_attribute=None):
super(self.__class__, self).__init__(Tags.RESPONSE_PAYLOAD)
self.unique_identifier = unique_identifier
self.template_attribute = template_attribute
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.unique_identifier = attributes.UniqueIdentifier()
self.unique_identifier.read(tstream)
if self.is_tag_next(Tags.TEMPLATE_ATTRIBUTE, tstream):
self.template_attribute = TemplateAttribute()
self.template_attribute.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the request payload
self.unique_identifier.write(tstream)
if self.template_attribute is not None:
self.template_attribute.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 4.11
class GetRequestPayload(Struct):
# 9.1.3.2.2
class KeyCompressionType(Enumeration):
ENUM_TYPE = enums.KeyCompressionType
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.KEY_COMPRESSION_TYPE)
# 9.1.3.2.3
class KeyFormatType(Enumeration):
ENUM_TYPE = enums.KeyFormatType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_FORMAT_TYPE)
def __init__(self,
unique_identifier=None,
key_format_type=None,
key_compression_type=None,
key_wrapping_specification=None):
super(self.__class__, self).__init__(tag=enums.Tags.REQUEST_PAYLOAD)
self.unique_identifier = unique_identifier
self.key_format_type = key_format_type
self.key_compression_type = key_compression_type
self.key_wrapping_specification = key_wrapping_specification
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
if self.is_tag_next(Tags.UNIQUE_IDENTIFIER, tstream):
self.unique_identifier = attributes.UniqueIdentifier()
self.unique_identifier.read(tstream)
if self.is_tag_next(Tags.KEY_FORMAT_TYPE, tstream):
self.key_format_type = GetRequestPayload.KeyFormatType()
self.key_format_type.read(tstream)
if self.is_tag_next(Tags.KEY_COMPRESSION_TYPE, tstream):
self.key_compression_type = GetRequestPayload.KeyCompressionType()
self.key_compression_type.read(tstream)
if self.is_tag_next(Tags.KEY_WRAPPING_SPECIFICATION, tstream):
self.key_wrapping_specification = KeyWrappingSpecification()
self.key_wrapping_specification.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the request payload
if self.unique_identifier is not None:
self.unique_identifier.write(tstream)
if self.key_format_type is not None:
self.key_format_type.write(tstream)
if self.key_compression_type is not None:
self.key_compression_type.write(tstream)
if self.key_wrapping_specification is not None:
self.key_wrapping_specification.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation
pass
class GetResponsePayload(Struct):
def __init__(self,
object_type=None,
unique_identifier=None,
secret=None):
super(self.__class__, self).__init__(tag=Tags.RESPONSE_PAYLOAD)
self.object_type = object_type
self.unique_identifier = unique_identifier
self.secret = secret
self.secret_factory = SecretFactory()
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.object_type = attributes.ObjectType()
self.unique_identifier = attributes.UniqueIdentifier()
self.object_type.read(tstream)
self.unique_identifier.read(tstream)
secret_type = self.object_type.enum
self.secret = self.secret_factory.create_secret(secret_type)
self.secret.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.object_type.write(tstream)
self.unique_identifier.write(tstream)
self.secret.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 4.21
class DestroyRequestPayload(Struct):
def __init__(self,
unique_identifier=None):
super(self.__class__, self).__init__(enums.Tags.REQUEST_PAYLOAD)
self.unique_identifier = unique_identifier
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
if self.is_tag_next(Tags.UNIQUE_IDENTIFIER, tstream):
self.unique_identifier = attributes.UniqueIdentifier()
self.unique_identifier.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
if self.unique_identifier is not None:
self.unique_identifier.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class DestroyResponsePayload(Struct):
def __init__(self,
unique_identifier=None):
super(self.__class__, self).__init__(enums.Tags.RESPONSE_PAYLOAD)
self.unique_identifier = unique_identifier
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.unique_identifier = attributes.UniqueIdentifier()
self.unique_identifier.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.unique_identifier.write(tstream)
# Write the length and value of the request payload
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
REQUEST_MAP = {enums.Operation.CREATE: CreateRequestPayload,
enums.Operation.GET: GetRequestPayload,
enums.Operation.DESTROY: DestroyRequestPayload,
enums.Operation.REGISTER: RegisterRequestPayload}
RESPONSE_MAP = {enums.Operation.CREATE: CreateResponsePayload,
enums.Operation.GET: GetResponsePayload,
enums.Operation.DESTROY: DestroyResponsePayload,
enums.Operation.REGISTER: RegisterResponsePayload}

845
kmip/core/objects.py Normal file
View File

@ -0,0 +1,845 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
import attributes
from kmip.core.attributes import CryptographicParameters
from kmip.core.factories.attribute_values import AttributeValueFactory
from kmip.core.factories.keys import KeyFactory
from kmip.core import enums
from kmip.core.enums import AttributeType
from kmip.core.enums import Tags
from kmip.core.enums import Types
from kmip.core.enums import CredentialType
from kmip.core.errors import ErrorStrings
from kmip.core.primitives import Struct
from kmip.core.primitives import TextString
from kmip.core.primitives import ByteString
from kmip.core.primitives import Integer
from kmip.core.primitives import Enumeration
from utils import BytearrayStream
# 2.1
# 2.1.1
class Attribute(Struct):
class AttributeName(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.ATTRIBUTE_NAME)
class AttributeIndex(Integer):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.ATTRIBUTE_INDEX)
def __init__(self,
attribute_name=None,
attribute_index=None,
attribute_value=None):
super(self.__class__, self).__init__(tag=Tags.ATTRIBUTE)
self.value_factory = AttributeValueFactory()
self.attribute_name = attribute_name
self.attribute_index = attribute_index
self.attribute_value = attribute_value
if attribute_value is not None:
attribute_value.tag = Tags.ATTRIBUTE_VALUE
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the name of the attribute
self.attribute_name = Attribute.AttributeName()
self.attribute_name.read(tstream)
# Read the attribute index if it is next
if self.is_tag_next(Tags.ATTRIBUTE_INDEX, tstream):
self.attribute_index = Attribute.AttributeIndex()
self.attribute_index.read(tstream)
# Lookup the attribute class that belongs to the attribute name
name = self.attribute_name.value
enum_name = name.replace('.', '_').replace(' ', '_').upper()
enum_type = None
try:
enum_type = AttributeType[enum_name]
except KeyError:
# Likely custom attribute, pass raw name string as attribute type
enum_type = name
value = self.value_factory.create_attribute_value(enum_type, None)
self.attribute_value = value
self.attribute_value.tag = Tags.ATTRIBUTE_VALUE
self.attribute_value.read(tstream)
self.is_oversized(tstream)
def write(self, ostream):
tstream = BytearrayStream()
self.attribute_name.write(tstream)
if self.attribute_index is not None:
self.attribute_index.write(tstream)
self.attribute_value.write(tstream)
# Write the length and value of the attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
# 2.1.2
class Credential(Struct):
class CredentialType(Enumeration):
ENUM_TYPE = CredentialType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.CREDENTIAL_TYPE)
class UsernamePasswordCredential(Struct):
class Username(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.USERNAME)
class Password(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.PASSWORD)
def __init__(self, username=None, password=None):
super(self.__class__, self).__init__(tag=Tags.CREDENTIAL_VALUE)
self.username = username
self.password = password
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the username of the credential
self.username = self.Username()
self.username.read(tstream)
# Read the password if it is next
if self.is_tag_next(Tags.PASSWORD, tstream):
self.password = self.Password()
self.password.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.username.write(tstream)
if self.password is not None:
self.password.write(tstream)
# Write the length and value of the credential
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
pass
class DeviceCredential(Struct):
class DeviceSerialNumber(TextString):
def __init__(self, value=None):
super(Credential.DeviceCredential.DeviceSerialNumber, self).\
__init__(value, Tags.DEVICE_SERIAL_NUMBER)
class Password(TextString):
def __init__(self, value=None):
super(Credential.DeviceCredential.Password, self).\
__init__(value, Tags.PASSWORD)
class DeviceIdentifier(TextString):
def __init__(self, value=None):
super(Credential.DeviceCredential.DeviceIdentifier, self).\
__init__(value, Tags.DEVICE_IDENTIFIER)
class NetworkIdentifier(TextString):
def __init__(self, value=None):
super(Credential.DeviceCredential.NetworkIdetifier, self).\
__init__(value, Tags.NETWORK_IDENTIFIER)
class MachineIdentifier(TextString):
def __init__(self, value=None):
super(Credential.DeviceCredential.MachineIdentifier, self).\
__init__(value, Tags.MACHINE_IDENTIFIER)
class MediaIdentifier(TextString):
def __init__(self, value=None):
super(Credential.DeviceCredential.MediaIdentifier, self).\
__init__(value, Tags.MEDIA_IDENTIFIER)
def __init__(self,
device_serial_number=None,
password=None,
device_identifier=None,
network_identifier=None,
machine_identifier=None,
media_identifier=None):
super(self.__class__, self).__init__(tag=Tags.CREDENTIAL_VALUE)
super.device_serial_number = device_serial_number
super.password = password
super.device_identifier = device_identifier
super.network_identifier = network_identifier
super.machine_identifier = machine_identifier
super.media_identifier = media_identifier
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the password if it is next
if self.is_tag_next(Tags.DEVICE_SERIAL_NUMBER, tstream):
self.device_serial_number = self.DeviceSerialNumber()
self.device_serial_number.read(tstream)
# Read the password if it is next
if self.is_tag_next(Tags.PASSWORD, tstream):
self.password = self.Password()
self.password.read(tstream)
# Read the password if it is next
if self.is_tag_next(Tags.DEVICE_IDENTIFIER, tstream):
self.device_identifier = self.DeviceIdentifier()
self.device_identifier.read(tstream)
# Read the password if it is next
if self.is_tag_next(Tags.NETWORK_IDENTIFIER, tstream):
self.network_identifier = self.NetworkIdentifier()
self.network_identifier.read(tstream)
# Read the password if it is next
if self.is_tag_next(Tags.MACHINE_IDENTIFIER, tstream):
self.machine_identifier = self.MachineIdentifier()
self.machine_identifier.read(tstream)
# Read the password if it is next
if self.is_tag_next(Tags.MEDIA_IDENTIFIER, tstream):
self.media_identifier = self.MediaIdentifier()
self.media_identifier.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
if self.device_serial_number is not None:
self.device_serial_number.write(tstream)
if self.password is not None:
self.password.write(tstream)
if self.device_identifier is not None:
self.device_identifier.write(tstream)
if self.network_identifier is not None:
self.network_identifier.write(tstream)
if self.machine_identifier is not None:
self.machine_identifier.write(tstream)
if self.media_identifier is not None:
self.media_identifier.write(tstream)
# Write the length and value of the credential
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
pass
def __init__(self, credential_type=None, credential_value=None):
super(self.__class__, self).__init__(tag=Tags.CREDENTIAL)
self.credential_type = credential_type
self.credential_value = credential_value
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
# Read the type of the credential
self.credential_type = self.CredentialType()
self.credential_type.read(tstream)
# Use the type to determine what credential value to read
if self.credential_type.enum is CredentialType.USERNAME_AND_PASSWORD:
self.credential_value = self.UsernamePasswordCredential()
elif self.credential_type.enum is CredentialType.DEVICE:
self.credential_value = self.DeviceCredential()
else:
# TODO (peter-hamilton) Use more descriptive error here
raise NotImplementedError()
self.credential_value.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.credential_type.write(tstream)
self.credential_value.write(tstream)
# Write the length and value of the credential
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
pass
# 2.1.3
class KeyBlock(Struct):
class KeyFormatType(Enumeration):
ENUM_TYPE = enums.KeyFormatType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_FORMAT_TYPE)
class KeyCompressionType(Enumeration):
ENUM_TYPE = enums.KeyCompressionType
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.KEY_COMPRESSION_TYPE)
def __init__(self,
key_format_type=None,
key_compression_type=None,
key_value=None,
cryptographic_algorithm=None,
cryptographic_length=None,
key_wrapping_data=None):
super(self.__class__, self).__init__(Tags.KEY_BLOCK)
self.key_format_type = key_format_type
self.key_compression_type = key_compression_type
self.key_value = key_value
self.cryptographic_algorithm = cryptographic_algorithm
self.cryptographic_length = cryptographic_length
self.key_wrapping_data = key_wrapping_data
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.key_format_type = KeyBlock.KeyFormatType()
self.key_format_type.read(tstream)
key_format_type = self.key_format_type.enum
if self.is_tag_next(Tags.KEY_COMPRESSION_TYPE, tstream):
self.key_compression_type = KeyBlock.KeyCompressionType()
self.key_compression_type.read(tstream)
self.key_value = KeyValue(key_format_type=key_format_type)
self.key_value.read(tstream)
if self.is_tag_next(Tags.CRYPTOGRAPHIC_ALGORITHM, tstream):
self.cryptographic_algorithm = attributes.CryptographicAlgorithm()
self.cryptographic_algorithm.read(tstream)
if self.is_tag_next(Tags.CRYPTOGRAPHIC_LENGTH, tstream):
self.cryptographic_length = attributes.CryptographicLength()
self.cryptographic_length.read(tstream)
if self.is_tag_next(Tags.KEY_WRAPPING_DATA, tstream):
self.key_wrapping_data = KeyWrappingData()
self.key_wrapping_data.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.key_format_type.write(tstream)
if self.key_compression_type is not None:
self.key_compression_type.write(tstream)
self.key_value.write(tstream)
if self.cryptographic_algorithm is not None:
self.cryptographic_algorithm.write(tstream)
if self.cryptographic_length is not None:
self.cryptographic_length.write(tstream)
if self.key_wrapping_data is not None:
self.key_wrapping_data.write(tstream)
# Write the length and value of the credential
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
if self.key_format_type is not None:
if type(self.key_format_type) is not KeyBlock.KeyFormatType:
member = 'KeyBlock.key_format_type'
exp_type = KeyBlock.KeyFormatType
rcv_type = type(self.key_format_type)
msg = ErrorStrings.BAD_EXP_RECV.format(member, 'type',
exp_type, rcv_type)
raise TypeError(msg)
# 2.1.4
class KeyValueString(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.KEY_VALUE)
class KeyValueStruct(Struct):
def __init__(self,
key_format_type=None,
key_material=None,
attributes=None):
super(self.__class__, self).__init__(Tags.KEY_VALUE)
self.key_format_type = key_format_type
self.key_material = key_material
self.attributes = attributes
self.key_factory = KeyFactory()
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.key_material = self.key_factory.create_key(self.key_format_type)
self.key_material.read(tstream)
self.attributes = list()
# Read the attributes, 0 or more
while self.is_tag_next(Tags.ATTRIBUTE, tstream):
attribute = Attribute()
attribute.read(tstream)
self.attributes.append(attribute)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.key_material.write(tstream)
if self.attributes is not None:
for attribute in self.attributes:
attribute.write(tstream)
# Write the length and value of the credential
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class KeyValue(Struct):
'''
KeyValue can be either a ByteString or a Struct. Therefore, this class
acts as a wrapper for two different KeyValue objects, KeyValueString,
which represents the ByteString format, and KeyValueStruct, which
represents the Struct format, both of which are defined above. This
KeyValue object does not read or write itself; instead, it reads and
writes its internal key_value attribute, which is either a KeyValueString
or a KeyValueStruct.
When reading, the class determines what the format of its internal
structure should be by looking at the type of the object it will read
using KeyValue.is_type_next(). This is one of the only places in the
code where this approach is used.
'''
def __init__(self,
key_value=None,
key_format_type=None):
super(self.__class__, self).__init__(Tags.KEY_VALUE)
self.key_value = key_value
self.key_format_type = key_format_type
if self.key_value is not None:
self.type = key_value.type
self.validate()
def read(self, istream):
if self.is_type_next(Types.BYTE_STRING, istream):
self.key_value = KeyValueString()
self.key_value.read(istream)
elif self.is_type_next(Types.STRUCTURE, istream):
kft = self.key_format_type
self.key_value = KeyValueStruct(key_format_type=kft)
self.key_value.read(istream)
def write(self, ostream):
tstream = BytearrayStream()
self.key_value.write(tstream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.1.5
class WrappingMethod(Enumeration):
ENUM_TYPE = enums.WrappingMethod
def __init__(self, value=None):
super(WrappingMethod, self).__init__(value, Tags.WRAPPING_METHOD)
class EncodingOption(Enumeration):
ENUM_TYPE = enums.EncodingOption
def __init__(self, value=None):
super(WrappingMethod, self).__init__(value, Tags.ENCODING_OPTION)
class KeyInformation(Struct):
def __init__(self,
unique_identifier=None,
cryptographic_parameters=None,
tag=Tags.ENCRYPTION_KEY_INFORMATION):
super(self.__class__, self).\
__init__(tag=Tags.ENCRYPTION_KEY_INFORMATION)
self.unique_identifier = unique_identifier
self.cryptographic_parameters = cryptographic_parameters
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.unique_identifier = attributes.UniqueIdentifier()
self.unique_identifier.read(tstream)
if self.is_tag_next(Tags.CRYPTOGRAPHIC_PARAMETERS, tstream):
self.cryptographic_parameters = CryptographicParameters()
self.cryptographic_parameters.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.unique_identifier.write(tstream)
if self.cryptographic_parameters is not None:
self.cryptographic_parameters.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class EncryptionKeyInformation(KeyInformation):
def __init__(self,
unique_identifier=None,
cryptographic_parameters=None,
tag=Tags.ENCRYPTION_KEY_INFORMATION):
super(self.__class__, self).\
__init__(unique_identifier, cryptographic_parameters, tag)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class MACSignatureKeyInformation(KeyInformation):
def __init__(self,
unique_identifier=None,
cryptographic_parameters=None,
tag=Tags.MAC_SIGNATURE_KEY_INFORMATION):
super(self.__class__, self).\
__init__(unique_identifier, cryptographic_parameters, tag)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class KeyWrappingData(Struct):
class MACSignature(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.MAC_SIGNATURE)
class IVCounterNonce(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.IV_COUNTER_NONCE)
def __init__(self,
wrapping_method=None,
encryption_key_information=None,
mac_signature_key_information=None,
mac_signature=None,
iv_counter_nonce=None,
encoding_option=None):
super(self.__class__, self).__init__(Tags.KEY_WRAPPING_DATA)
self.wrapping_method = wrapping_method
self.encryption_key_information = encryption_key_information
self.mac_signature_key_information = mac_signature_key_information
self.mac_signature = mac_signature
self.iv_counter_nonce = iv_counter_nonce
self.encoding_option = encoding_option
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.wrapping_method = WrappingMethod()
self.wrapping_method.read(tstream)
if self.is_tag_next(Tags.ENCRYPTION_KEY_INFORMATION, tstream):
self.encryption_key_information = EncryptionKeyInformation()
self.encryption_key_information.read(tstream)
if self.is_tag_next(Tags.MAC_SIGNATURE_KEY_INFORMATION, tstream):
self.mac_signature_key_information = MACSignatureKeyInformation()
self.mac_signature_key_information.read(tstream)
if self.is_tag_next(Tags.MAC_SIGNATURE, tstream):
self.mac_signature = KeyWrappingData.MACSignature()
self.mac_signature.read(tstream)
if self.is_tag_next(Tags.IV_COUNTER_NONCE, tstream):
self.iv_counter_nonce = KeyWrappingData.IVCounterNonce()
self.iv_counter_nonce.read(tstream)
if self.is_tag_next(Tags.ENCODING_OPTION, tstream):
self.encoding_option = EncodingOption()
self.encoding_option.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the key wrapping data
self.wrapping_method.write(tstream)
if self.encryption_key_information is not None:
self.encryption_key_information.write(tstream)
if self.mac_signature_key_information is not None:
self.mac_signature_key_information.write(tstream)
if self.mac_signature is not None:
self.mac_signature.write(tstream)
if self.iv_counter_nonce is not None:
self.iv_counter_nonce.write(tstream)
if self.encoding_option is not None:
self.encoding_option.write(tstream)
# Write the length and value of the key wrapping data
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation
pass
# 2.1.6
class KeyWrappingSpecification(Struct):
class AttributeName(TextString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.ATTRIBUTE_NAME)
def __init__(self,
wrapping_method=None,
encryption_key_information=None,
mac_signature_key_information=None,
attribute_name=None,
encoding_option=None):
super(self.__class__, self).\
__init__(tag=Tags.KEY_WRAPPING_SPECIFICATION)
self.wrapping_method = wrapping_method
self.encryption_key_information = encryption_key_information
self.mac_signature_key_information = mac_signature_key_information
self.attribute_name = attribute_name
self.encoding_option = encoding_option
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.wrapping_method = WrappingMethod()
self.wrapping_method.read(tstream)
if self.is_tag_next(Tags.ENCRYPTION_KEY_INFORMATION, tstream):
self.encryption_key_information = EncryptionKeyInformation()
self.encryption_key_information.read(tstream)
if self.is_tag_next(Tags.MAC_SIGNATURE_KEY_INFORMATION, tstream):
self.mac_signature_key_information = MACSignatureKeyInformation()
self.mac_signature_key_information.read(tstream)
if self.is_tag_next(Tags.ATTRIBUTE_NAME, tstream):
self.attribute_name = KeyWrappingSpecification.AttributeName()
self.attribute_name.read(tstream)
if self.is_tag_next(Tags.ENCODING_OPTION, tstream):
self.encoding_option = EncodingOption()
self.encoding_option.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the contents of the key wrapping data
self.wrapping_method.write(tstream)
if self.encryption_key_information is not None:
self.encryption_key_information.write(tstream)
if self.mac_signature_key_information is not None:
self.mac_signature_key_information.write(tstream)
if self.attribute_name is not None:
self.attribute_name.write(tstream)
if self.encoding_option is not None:
self.encoding_option.write(tstream)
# Write the length and value of the key wrapping data
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.1.8
class TemplateAttribute(Struct):
def __init__(self,
names=None,
attributes=None):
super(self.__class__, self).__init__(tag=Tags.TEMPLATE_ATTRIBUTE)
self.names = names
self.attributes = attributes
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.names = list()
self.attributes = list()
# Read the names of the template attribute, 0 or more
while self.is_tag_next(Tags.NAME, tstream):
name = attributes.Name()
name.read(tstream)
self.names.append(name)
# Read the attributes of the template attribute, 0 or more
while self.is_tag_next(Tags.ATTRIBUTE, tstream):
attribute = Attribute()
attribute.read(tstream)
self.attributes.append(attribute)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the names and attributes of the template attribute
if self.names is not None:
for name in self.names:
name.write(tstream)
if self.attributes is not None:
for attribute in self.attributes:
attribute.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass

618
kmip/core/primitives.py Normal file
View File

@ -0,0 +1,618 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from struct import pack, unpack
from enum import Enum
from kmip.core.enums import Types
from kmip.core.enums import Tags
from kmip.core.errors import ErrorStrings
import errors
import utils
class Base(object):
TAG_SIZE = 3
TYPE_SIZE = 1
LENGTH_SIZE = 4
def __init__(self, tag=Tags.DEFAULT, type=Types.DEFAULT):
self.tag = tag
self.type = type
self.length = None
# TODO (peter-hamilton) Convert this into a classmethod, class name can be
# obtained from cls parameter that replaces self
def is_oversized(self, stream):
extra = len(stream.peek())
if extra > 0:
raise errors.StreamNotEmptyError(Base.__name__, extra)
def read_tag(self, istream):
# Read in the bytes for the tag
tts = istream.read(self.TAG_SIZE)
tag = unpack('!I', '\x00' + tts[0:self.TAG_SIZE])[0]
enum_tag = Tags(tag)
# Verify that the tag matches for the current object
if enum_tag is not self.tag:
raise errors.ReadValueError(Base.__name__, 'tag',
hex(self.tag.value), hex(tag))
def read_type(self, istream):
# Read in the bytes for the type
tts = istream.read(self.TYPE_SIZE)
num_bytes = len(tts)
if num_bytes != self.TYPE_SIZE:
min_bytes = 'a minimum of {0} bytes'.format(self.TYPE_SIZE)
raise errors.ReadValueError(Base.__name__, 'type', min_bytes,
'{0} bytes'.format(num_bytes))
typ = unpack('!B', tts)[0]
enum_typ = Types(typ)
if enum_typ is not self.type:
raise errors.ReadValueError(Base.__name__, 'type',
self.type.value, typ)
def read_length(self, istream):
# Read in the bytes for the length
lst = istream.read(self.LENGTH_SIZE)
num_bytes = len(lst)
if num_bytes != self.LENGTH_SIZE:
min_bytes = 'a minimum of {0} bytes'.format(self.LENGTH_SIZE)
raise errors.ReadValueError(Base.__name__, 'length', min_bytes,
'{0} bytes'.format(num_bytes))
length = unpack('!I', lst)[0]
# Verify that the length matches the expected length, if one exists
if self.length is not None:
if length is not self.length:
raise errors.ReadValueError(Base.__name__, 'length',
self.length, length)
else:
self.length = length
def read_value(self, istream):
raise NotImplementedError()
def read(self, istream):
self.read_tag(istream)
self.read_type(istream)
self.read_length(istream)
def write_tag(self, ostream):
# Write the tag to the output stream
ostream.write(pack('!I', self.tag.value)[1:])
def write_type(self, ostream):
if type(self.type) is not Types:
msg = ErrorStrings.BAD_EXP_RECV
raise TypeError(msg.format(Base.__name__, 'type',
Types, type(self.type)))
ostream.write(pack('!B', self.type.value))
def write_length(self, ostream):
if type(self.length) is not int:
msg = ErrorStrings.BAD_EXP_RECV
raise TypeError(msg.format(Base.__name__, 'length',
int, type(self.length)))
num_bytes = utils.count_bytes(self.length)
if num_bytes > self.LENGTH_SIZE:
raise errors.WriteOverflowError(Base.__name__, 'length',
self.LENGTH_SIZE, num_bytes)
ostream.write(pack('!I', self.length))
def write_value(self, ostream):
raise NotImplementedError()
def write(self, ostream):
self.write_tag(ostream)
self.write_type(ostream)
self.write_length(ostream)
def validate(self):
raise NotImplementedError()
@staticmethod
def is_tag_next(tag, stream):
next_tag = stream.peek(Base.TAG_SIZE)
if len(next_tag) != Base.TAG_SIZE:
return False
next_tag = unpack('!I', '\x00' + next_tag)[0]
if next_tag == tag.value:
return True
else:
return False
@staticmethod
def is_type_next(kmip_type, stream):
tag_type_size = Base.TAG_SIZE + Base.TYPE_SIZE
tt = stream.peek(tag_type_size)
if len(tt) != tag_type_size:
return False
typ = unpack('!B', tt[Base.TAG_SIZE:])[0]
if typ == kmip_type.value:
return True
else:
return False
class Struct(Base):
def __init__(self, tag=Tags.DEFAULT):
super(Struct, self).__init__(tag, type=Types.STRUCTURE)
def __repr__(self):
return '<Struct>'
class Integer(Base):
LENGTH = 4
def __init__(self, value=None, tag=Tags.DEFAULT):
super(Integer, self).__init__(tag, type=Types.INTEGER)
self.value = value
self.length = self.LENGTH
self.padding_length = self.LENGTH
self.validate()
def read_value(self, istream):
if self.length is not self.LENGTH:
raise errors.ReadValueError(Integer.__name__, 'length',
self.LENGTH, self.length)
self.value = unpack('!i', str(istream.read(self.length)))[0]
pad = unpack('!i', str(istream.read(self.padding_length)))[0]
if pad is not 0:
raise errors.ReadValueError(Integer.__name__, 'pad', 0,
pad)
self.validate()
def read(self, istream):
super(Integer, self).read(istream)
self.read_value(istream)
def write_value(self, ostream):
ostream.write(pack('!i', self.value))
ostream.write(pack('!i', 0))
def write(self, ostream):
super(Integer, self).write(ostream)
self.write_value(ostream)
def validate(self):
self.__validate()
def __validate(self):
if self.value is not None:
data_type = type(self.value)
if data_type is not int:
raise errors.StateTypeError(Integer.__name__, int,
data_type)
num_bytes = utils.count_bytes(self.value)
if num_bytes > self.length:
raise errors.StateOverflowError(Integer.__name__,
'value', self.length,
num_bytes)
def __repr__(self):
return '<Integer, %d>' % (self.value)
class LongInteger(Base):
LENGTH = 8
def __init__(self, value=None, tag=Tags.DEFAULT):
super(LongInteger, self).__init__(tag, type=Types.LONG_INTEGER)
self.value = value
self.length = self.LENGTH
self.validate()
def read_value(self, istream):
if self.length is not self.LENGTH:
raise errors.ReadValueError(LongInteger.__name__, 'length',
self.LENGTH, self.length)
self.value = unpack('!q', str(istream.read(self.length)))[0]
self.validate()
def read(self, istream):
super(LongInteger, self).read(istream)
self.read_value(istream)
def write_value(self, ostream):
ostream.write(pack('!q', self.value))
def write(self, ostream):
super(LongInteger, self).write(ostream)
self.write_value(ostream)
def validate(self):
self.__validate()
def __validate(self):
if self.value is not None:
data_type = type(self.value)
if data_type not in (int, long):
raise errors.StateTypeError(LongInteger.__name__,
'{0} or {1}'.format(int, long),
data_type)
num_bytes = utils.count_bytes(self.value)
if num_bytes > self.length:
raise errors.StateOverflowError(LongInteger.__name__,
'value', self.length,
num_bytes)
def __repr__(self):
return '<Long Integer, %d>' % (self.value)
class BigInteger(Base):
BLOCK_SIZE = 8
SHIFT_SIZE = 64
def __init__(self, value=None, tag=Tags.DEFAULT):
super(BigInteger, self).__init__(tag, type=Types.BIG_INTEGER)
self.value = value
if self.value is not None:
self.real_length = utils.count_bytes(self.value)
self.padding_length = self.BLOCK_SIZE - (self.length %
self.BLOCK_SIZE)
if self.padding_length == self.BLOCK_SIZE:
self.padding_length = 0
else:
self.length = None
self.padding_length = None
self.validate()
def read_value(self, istream):
if (self.length < self.BLOCK_SIZE) or (self.length % self.BLOCK_SIZE):
raise errors.InvalidLengthError(BigInteger.__name__,
('multiple'
'of {0}'.format(self.BLOCK_SIZE)),
self.length)
self.value = 0
num_blocks = self.length / self.BLOCK_SIZE
# Read first block as signed data
self.value = unpack('!q', str(istream.read(self.BLOCK_SIZE)))[0]
# Shift current value and add on next unsigned block
for _ in xrange(num_blocks - 1):
self.value = self.value << self.SHIFT_SIZE
stream_data = istream.read(self.BLOCK_SIZE)
self.value += unpack('!Q', stream_data)[0]
self.validate()
def read(self, istream):
super(BigInteger, self).read(istream)
self.read_value(istream)
def write_value(self, ostream):
# 1. Determine the sign of the value (+/-); save it.
# 2. Extend hex of value with 0s until encoding is right size (8x).
# 3. Write out each block of the encoding as signed, 2s complement:
# pack('!q', sign * block)
# Determine sign for padding
pad_byte = 0x00
pad_nybl = 0x0
if self.value < 0:
pad_byte = 0xff
pad_nybl = 0xf
# Compose padding bytes
pad = ''
for _ in xrange(self.padding_length):
pad += hex(pad_byte)[2:]
str_rep = hex(self.value).rstrip("Ll")[2:]
if len(str_rep) % 2:
pad += hex(pad_nybl)[2]
# Compose value for block-based write
str_rep = pad + str_rep
num_blocks = len(str_rep) / self.BLOCK_SIZE
# Write first block as signed data
block = int(str_rep[0:self.BLOCK_SIZE], 16)
ostream.write(pack('!q', block))
# Write remaining blocks as unsigned data
for i in xrange(1, num_blocks):
block = str_rep[(self.BLOCK_SIZE * i):(self.BLOCK_SIZE * (i + 1))]
block = int(block, 16)
ostream.write(pack('!Q', block))
def write(self, ostream):
super(BigInteger, self).write(ostream)
self.write_value(ostream)
def validate(self):
self.__validate()
def __validate(self):
if self.value is not None:
data_type = type(self.value)
if data_type not in (int, long):
raise errors.StateTypeError(BigInteger.__name__,
'{0} or {1}'.format(int, long),
data_type)
num_bytes = utils.count_bytes(self.length)
if num_bytes > self.LENGTH_SIZE:
raise errors.StateOverflowError(BigInteger.__name__,
'length', self.LENGTH_SIZE,
num_bytes)
class Enumeration(Integer):
ENUM_TYPE = None
def __init__(self, value=None, tag=Tags.DEFAULT):
self.enum = value
self.validate()
if self.enum is None:
super(Enumeration, self).__init__(None, tag)
else:
super(Enumeration, self).__init__(self.enum.value, tag)
self.type = Types.ENUMERATION
def read(self, istream):
super(Enumeration, self).read(istream)
self.enum = self.ENUM_TYPE(self.value)
self.validate()
def write(self, ostream):
super(Enumeration, self).write(ostream)
def validate(self):
self.__validate()
def __validate(self):
if self.enum is not None:
if type(self.enum) is not self.ENUM_TYPE:
msg = ErrorStrings.BAD_EXP_RECV
raise TypeError(msg.format(Enumeration.__name__, 'value',
Enum, type(self.enum)))
def __repr__(self):
return '<Enumeration, %s, %d>' % (self.enum.name, self.enum.value)
class Boolean(Base):
def __init__(self, value=None, tag=Tags.DEFAULT):
super(Boolean, self).__init__(tag, type=Types.BOOLEAN)
self.value = value
self.length = 8
def read_value(self, istream):
value = unpack('!Q', str(istream[0:self.length]))[0]
if value == 1:
self.value = True
elif value == 0:
self.value = False
else:
raise errors.ReadValueError(Boolean.__name__, 'value',
value)
for _ in xrange(self.length):
istream.pop(0)
def read(self, istream):
super(Boolean, self).read(istream)
self.read_value(istream)
def write_value(self, ostream):
if self.value is None:
raise errors.WriteValueError(Boolean.__name__, 'value',
self.value)
data_buffer = bytearray()
if isinstance(self.value, type(True)):
if self.value:
data_buffer.extend(pack('!Q', 1))
else:
data_buffer.extend(pack('!Q', 0))
else:
raise errors.WriteTypeError(Boolean.__name__, 'value',
type(self.value))
ostream.extend(data_buffer)
def write(self, ostream):
super(Boolean, self).write(ostream)
self.write_value(ostream)
def validate(self):
self.__validate()
def __validate(self):
pass
def __repr__(self):
return '<Boolean, %s>' % (self.value)
class TextString(Base):
PADDING_SIZE = 8
BYTE_FORMAT = '!c'
def __init__(self, value=None, tag=Tags.DEFAULT):
super(TextString, self).__init__(tag, type=Types.TEXT_STRING)
self.value = value
self.validate()
if self.value is not None:
self.length = len(self.value)
self.padding_length = self.PADDING_SIZE - (self.length %
self.PADDING_SIZE)
if self.padding_length == self.PADDING_SIZE:
self.padding_length = 0
else:
self.length = None
self.padding_length = None
def read_value(self, istream):
# Read string text
self.value = ''
for _ in xrange(self.length):
self.value += unpack(self.BYTE_FORMAT, str(istream.read(1)))[0]
# Read padding and check content
self.padding_length = self.PADDING_SIZE - (self.length %
self.PADDING_SIZE)
if self.padding_length < self.PADDING_SIZE:
for _ in xrange(self.padding_length):
pad = unpack('!B', str(istream.read(1)))[0]
if pad is not 0:
raise errors.ReadValueError(TextString.__name__, 'pad', 0,
pad)
def read(self, istream):
super(TextString, self).read(istream)
self.read_value(istream)
self.validate()
def write_value(self, ostream):
# Write string to stream
for char in self.value:
ostream.write(pack(self.BYTE_FORMAT, char))
# Write padding to stream
for _ in xrange(self.padding_length):
ostream.write(pack('!B', 0))
def write(self, ostream):
super(TextString, self).write(ostream)
self.write_value(ostream)
def validate(self):
self.__validate()
def __validate(self):
if self.value is not None:
data_type = type(self.value)
if data_type is not str:
msg = ErrorStrings.BAD_EXP_RECV
raise TypeError(msg.format('TextString', 'value', str,
data_type))
def __repr__(self):
return '<TextString, %s>' % (self.value)
class ByteString(Base):
PADDING_SIZE = 8
BYTE_FORMAT = '!B'
def __init__(self, value=None, tag=Tags.DEFAULT):
super(ByteString, self).__init__(tag, type=Types.BYTE_STRING)
self.value = value
self.validate()
if self.value is not None:
self.length = len(self.value)
self.padding_length = self.PADDING_SIZE - (self.length %
self.PADDING_SIZE)
if self.padding_length == self.PADDING_SIZE:
self.padding_length = 0
else:
self.length = None
self.padding_length = None
def read_value(self, istream):
# Read bytes into bytearray
self.value = bytearray()
for _ in xrange(self.length):
self.value.append(istream.read(1))
# Read padding and check content
self.padding_length = self.PADDING_SIZE - (self.length %
self.PADDING_SIZE)
if self.padding_length == self.PADDING_SIZE:
self.padding_length = 0
if self.padding_length < self.PADDING_SIZE:
for _ in xrange(self.padding_length):
pad = unpack('!B', str(istream.read(1)))[0]
if pad is not 0:
raise errors.ReadValueError(TextString.__name__, 'pad', 0,
pad)
def read(self, istream):
super(ByteString, self).read(istream)
self.read_value(istream)
def write_value(self, ostream):
# Write bytes to stream
for byte in self.value:
ostream.write(pack(self.BYTE_FORMAT, byte))
# Write padding to stream
for _ in xrange(self.padding_length):
ostream.write(pack('!B', 0))
def write(self, ostream):
super(ByteString, self).write(ostream)
self.write_value(ostream)
def validate(self):
self.__validate()
def __validate(self):
if self.value is not None:
data_type = type(self.value)
if data_type is not bytearray:
msg = ErrorStrings.BAD_EXP_RECV
raise TypeError(msg.format('ByteString', 'value', bytearray,
data_type))
def __repr__(self):
return '<Integer, %s>' % (self.value)
class DateTime(LongInteger):
def __init__(self, value=None, tag=Tags.DEFAULT):
super(DateTime, self).__init__(value, tag)
self.type = Types.DATE_TIME
class Interval(Integer):
def __init__(self, value=None, tag=Tags.DEFAULT):
super(Interval, self).__init__(value, tag)
self.type = Types.INTERVAL

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,47 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.repo.repo import ManagedObjectRepo
class MemRepo(ManagedObjectRepo):
def __init__(self):
self.repo = {}
self.uuid = 1
def save(self, managed_object, attributes):
# TODO (nate) verify the parameters
uuid = "{0}".format(self.uuid)
self.repo[uuid] = (managed_object, attributes)
self.uuid += 1
return uuid
def get(self, uuid):
if uuid is None or uuid not in self.repo:
return (None, None)
return self.repo[uuid]
def update(self, uuid, managed_object, attributes):
if uuid is None:
return False
self.repo[uuid] = (managed_object, attributes)
return True
def delete(self, uuid):
if uuid is None or uuid not in self.repo:
return False
del self.repo[uuid]
return True

73
kmip/core/repo/repo.py Normal file
View File

@ -0,0 +1,73 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
class ManagedObjectRepo(object):
"""Stores and manages KMIP managed objects.
The KMIP specification details the managed objects that are stored by a
KMIP server. This repository abstraction is an interface for KMIP servers
to store managed objects.
"""
def __init__(self):
pass
def save(self, managed_object, attributes):
"""Save a managed object
This saves a managed object into the repository and returns a UUID
string that can be used to reference the object in the repository.
:param managed_object: managed object to save from secrets.py
:param attributes: attributes to store with the managed object
:returns: a UUID string that can be used to retrieve the object later
"""
raise NotImplementedError
def get(self, uuid):
"""Retrieve a managed object
Retrieve a managed object from the repository. The UUID is used to
identify the managed object to return. The UUID is returned from the
save call.
A tuple is returned that contains the managed object and all of its
attributes.
:param uuid: UUID of the managed object
:returns: (managed_object, attributes) if object exists, otherwise
(None, None)
"""
raise NotImplementedError
def update(self, uuid, managed_object, attributes):
"""Updates a managed object
Updates the values for a managed_object.
:param uuid: UUID of the managed object
:param managed_object: managed object
:param attributes: attributes to store with the managed object
:returns: True if object existed and successfully updated, otherwise
False
"""
raise NotImplementedError
def delete(self, uuid):
"""Delete a managed object from the repository
Delete a managed object from the repository.
:param uuid: UUID of the managed object
:returns: True if successfully deleted, False if not found
"""
raise NotImplementedError

408
kmip/core/secrets.py Normal file
View File

@ -0,0 +1,408 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.attributes import CertificateType
from kmip.core import enums
from kmip.core.enums import Tags
from kmip.core.objects import Attribute
from kmip.core.objects import KeyBlock
from kmip.core.primitives import Struct
from kmip.core.primitives import Integer
from kmip.core.primitives import Enumeration
from kmip.core.primitives import BigInteger
from kmip.core.primitives import ByteString
from kmip.core.utils import BytearrayStream
# 2.2
# 2.2.1
class Certificate(Struct):
class CertificateValue(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.CERTIFICATE_VALUE)
def __init__(self,
certificate_type=None,
certificate_value=None):
super(self.__class__, self).__init__(Tags.CERTIFICATE)
self.certificate_type = certificate_type
self.certificate_value = certificate_value
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.certificate_type = CertificateType()
self.certificate_value = Certificate.CertificateValue()
self.certificate_type.read(tstream)
self.certificate_value.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
# Write the details of the certificate
self.certificate_type.write(tstream)
self.certificate_value.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.2
class KeyBlockKey(Struct):
def __init__(self, key_block=None, tag=Tags.DEFAULT):
super(KeyBlockKey, self).__init__(tag)
self.key_block = key_block
self.validate()
def read(self, istream):
super(KeyBlockKey, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.key_block = KeyBlock()
self.key_block.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.key_block.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(KeyBlockKey, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
class SymmetricKey(KeyBlockKey):
def __init__(self, key_block=None):
super(self.__class__, self).__init__(key_block, Tags.SYMMETRIC_KEY)
self.validate()
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.3
class PublicKey(KeyBlockKey):
def __init__(self, key_block=None):
super(self.__class__, self).__init__(key_block, Tags.PUBLIC_KEY)
self.validate()
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.4
class PrivateKey(KeyBlockKey):
def __init__(self, key_block=None):
super(self.__class__, self).__init__(key_block, Tags.PRIVATE_KEY)
self.validate()
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.5
class SplitKey(Struct):
class SplitKeyParts(Integer):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.SPLIT_KEY_PARTS)
class KeyPartIdentifier(Integer):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.KEY_PART_IDENTIFIER)
class SplitKeyThreshold(Integer):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.SPLIT_KEY_THRESHOLD)
class SplitKeyMethod(Enumeration):
ENUM_TYPE = enums.SplitKeyMethod
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.SPLIT_KEY_METHOD)
class PrimeFieldSize(BigInteger):
def __init__(self, value=None):
super(self.__class__, self).__init__(value,
Tags.PRIME_FIELD_SIZE)
def __init__(self,
split_key_parts=None,
key_part_identifier=None,
split_key_threshold=None,
split_key_method=None,
prime_field_size=None,
key_block=None):
super(self.__class__, self).__init__(Tags.SPLIT_KEY)
self.split_key_parts = split_key_parts
self.key_part_identifier = key_part_identifier
self.split_key_threshold = split_key_threshold
self.split_key_method = split_key_method
self.prime_field_size = prime_field_size
self.key_block = key_block
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.split_key_parts = SplitKey.SplitKeyParts()
self.split_key_parts.read(tstream)
self.key_part_identifier = SplitKey.KeyPartIdentifier()
self.key_part_identifier.read(tstream)
self.split_key_threshold = SplitKey.SplitKeyThreshold()
self.split_key_threshold.read(tstream)
if self.is_tag_next(Tags.PRIME_FIELD_SIZE, tstream):
self.prime_field_size = SplitKey.PrimeFieldSize()
self.prime_field_size.read(tstream)
self.key_block = KeyBlock()
self.key_block.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.split_key_parts.write(tstream)
self.key_part_identifier.write(tstream)
self.split_key_threshold.write(tstream)
self.split_key_method.write(tstream)
if self.prime_field_size is not None:
self.prime_field_size.write(tstream)
self.key_block.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.6
class Template(Struct):
def __init__(self, attributes=None):
super(self.__class__, self).__init__(Tags.TEMPLATE)
self.attributes = attributes
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.attributes = list()
attribute = Attribute()
attribute.read(tstream)
self.attributes.append(attribute)
while self.is_tag_next(Tags.ATTRIBUTE, tstream):
attribute = Attribute()
attribute.read(tstream)
self.attributes.append(attribute)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
for attribute in self.attributes:
attribute.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.7
class SecretData(Struct):
class SecretDataType(Enumeration):
ENUM_TYPE = enums.SecretDataType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.SECRET_DATA_TYPE)
def __init__(self,
secret_data_type=None,
key_block=None):
super(self.__class__, self).__init__(Tags.SECRET_DATA)
self.secret_data_type = secret_data_type
self.key_block = key_block
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.secret_data_type = SecretData.SecretDataType()
self.key_block = KeyBlock()
self.secret_data_type.read(tstream)
self.key_block.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.secret_data_type.write(tstream)
self.key_block.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass
# 2.2.8
class OpaqueObject(Struct):
class OpaqueDataType(Enumeration):
ENUM_TYPE = enums.OpaqueDataType
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.OPAQUE_DATA_TYPE)
class OpaqueDataValue(ByteString):
def __init__(self, value=None):
super(self.__class__, self).__init__(value, Tags.OPAQUE_DATA_VALUE)
def __init__(self,
opaque_data_type=None,
opaque_data_value=None):
super(self.__class__, self).__init__(Tags.OPAQUE_OBJECT)
self.opaque_data_type = opaque_data_type
self.opaque_data_value = opaque_data_value
self.validate()
def read(self, istream):
super(self.__class__, self).read(istream)
tstream = BytearrayStream(istream.read(self.length))
self.opaque_data_type = OpaqueObject.OpaqueDataType()
self.opaque_data_value = OpaqueObject.OpaqueDataValue()
self.opaque_data_type.read(tstream)
self.opaque_data_value.read(tstream)
self.is_oversized(tstream)
self.validate()
def write(self, ostream):
tstream = BytearrayStream()
self.opaque_data_type.write(tstream)
self.opaque_data_value.write(tstream)
# Write the length and value of the template attribute
self.length = tstream.length()
super(self.__class__, self).write(ostream)
ostream.write(tstream.buffer)
def validate(self):
self.__validate()
def __validate(self):
# TODO (peter-hamilton) Finish implementation.
pass

357
kmip/core/server.py Normal file
View File

@ -0,0 +1,357 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
import logging
import os
from kmip.core.attributes import CryptographicLength
from kmip.core.attributes import CryptographicAlgorithm
from kmip.core.attributes import ObjectType
from kmip.core.attributes import UniqueIdentifier
from kmip.core.enums import AttributeType as AT
from kmip.core.enums import CryptographicAlgorithm as CA
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
from kmip.core.enums import ObjectType as OT
from kmip.core.enums import ResultReason as ResultReasonEnum
from kmip.core.enums import ResultStatus as RS
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.factories.keys import KeyFactory
from kmip.core.factories.secrets import SecretFactory
from kmip.core.keys import RawKey
from kmip.core.messages.contents import KeyFormatType
from kmip.core.messages.contents import ResultStatus
from kmip.core.messages.contents import ResultReason
from kmip.core.messages.contents import ResultMessage
from kmip.core.objects import KeyBlock
from kmip.core.objects import KeyValue
from kmip.core.objects import KeyValueStruct
from kmip.core.objects import TemplateAttribute
from kmip.core.repo.mem_repo import MemRepo
from kmip.core.secrets import SymmetricKey
from kmip.services.results import CreateResult
from kmip.services.results import DestroyResult
from kmip.services.results import GetResult
from kmip.services.results import OperationResult
from kmip.services.results import RegisterResult
class KMIP(object):
def __init__(self):
pass
def create(self, object_type, template_attribute, credential=None):
raise NotImplementedError
def register(self, object_type, template_attribute, secret,
credential=None):
raise NotImplementedError
def get(self, uuid=None, key_format_type=None, key_compression_type=None,
key_wrapping_specification=None, credential=None):
raise NotImplementedError
def destroy(self, uuid, credential=None):
raise NotImplementedError
class KMIPImpl(KMIP):
def __init__(self):
super(self.__class__, self).__init__()
self.logger = logging.getLogger(__name__)
self.key_factory = KeyFactory()
self.secret_factory = SecretFactory()
self.attribute_factory = AttributeFactory()
self.repo = MemRepo()
def create(self, object_type, template_attribute, credential=None):
self.logger.debug('create() called')
self.logger.debug('object type = %s' % object_type)
bit_length = 256
attributes = template_attribute.attributes
ret_attributes = []
if object_type.enum != OT.SYMMETRIC_KEY:
self.logger.debug('invalid object type')
return self._get_invalid_field_result('invalid object type')
try:
alg_attr =\
self._validate_req_field(attributes,
AT.CRYPTOGRAPHIC_ALGORITHM.value,
(CA.AES.value,),
'unsupported algorithm')
len_attr = self._validate_req_field(attributes,
AT.CRYPTOGRAPHIC_LENGTH.value,
(128, 256, 512),
'unsupported key length',
False)
self._validate_req_field(attributes,
AT.CRYPTOGRAPHIC_USAGE_MASK.value,
(),
'')
except InvalidFieldException as e:
self.logger.debug('InvalidFieldException raised')
return e.result
crypto_alg = CryptographicAlgorithm(CA(alg_attr.attribute_value.value))
if len_attr is None:
self.logger.debug('cryptographic length not supplied')
attribute_type = AT.CRYPTOGRAPHIC_LENGTH
length_attribute = self.attribute_factory.\
create_attribute(attribute_type, bit_length)
attributes.append(length_attribute)
ret_attributes.append(length_attribute)
else:
bit_length = len_attr.attribute_value.value
key = self._gen_symmetric_key(bit_length, crypto_alg)
s_uuid, uuid_attribute = self._save(key, attributes)
ret_attributes.append(uuid_attribute)
template_attribute = TemplateAttribute(attributes=ret_attributes)
return CreateResult(ResultStatus(RS.SUCCESS),
object_type=object_type,
uuid=UniqueIdentifier(s_uuid),
template_attribute=template_attribute)
def register(self, object_type, template_attribute, secret,
credential=None):
self.logger.debug('register() called')
self.logger.debug('object type = %s' % object_type)
attributes = template_attribute.attributes
ret_attributes = []
if object_type is None:
self.logger.debug('invalid object type')
return self._get_missing_field_result('object type')
if object_type.enum != OT.SYMMETRIC_KEY:
self.logger.debug('invalid object type')
return self._get_invalid_field_result('invalid object type')
if secret is None or not isinstance(secret, SymmetricKey):
msg = 'object type does not match that of secret'
self.logger.debug(msg)
return self._get_invalid_field_result(msg)
self.logger.debug('Collecting all attributes')
if attributes is None:
attributes = []
attributes.extend(self._get_key_block_attributes(secret.key_block))
self.logger.debug('Verifying all attributes are valid and set')
try:
self._validate_req_field(attributes,
AT.CRYPTOGRAPHIC_ALGORITHM.value,
(CA.AES.value,),
'unsupported algorithm')
self._validate_req_field(attributes,
AT.CRYPTOGRAPHIC_LENGTH.value,
(128, 256, 512),
'unsupported key length')
self._validate_req_field(attributes,
AT.CRYPTOGRAPHIC_USAGE_MASK.value,
(),
'')
except InvalidFieldException as e:
self.logger.debug('InvalidFieldException raised')
return RegisterResult(e.result.result_status,
e.result.result_reason,
e.result.result_message)
s_uuid, uuid_attribute = self._save(secret, attributes)
ret_attributes.append(uuid_attribute)
template_attribute = TemplateAttribute(attributes=ret_attributes)
return RegisterResult(ResultStatus(RS.SUCCESS),
uuid=UniqueIdentifier(s_uuid),
template_attribute=template_attribute)
def get(self,
uuid=None,
key_format_type=None,
key_compression_type=None,
key_wrapping_specification=None,
credential=None):
self.logger.debug('get() called')
ret_value = RS.OPERATION_FAILED
if uuid is None or not hasattr(uuid, 'value'):
self.logger.debug('no uuid provided')
reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
message = ResultMessage('')
return GetResult(ResultStatus(ret_value), reason, message)
if key_format_type is None:
self.logger.debug('key format type is None, setting to raw')
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
if key_format_type.enum != KeyFormatTypeEnum.RAW:
self.logger.debug('key format type is not raw')
reason = ResultReason(ResultReasonEnum.
KEY_FORMAT_TYPE_NOT_SUPPORTED)
message = ResultMessage('')
return GetResult(ResultStatus(ret_value), reason, message)
if key_compression_type is not None:
self.logger.debug('key compression type is not None')
reason = ResultReason(ResultReasonEnum.
KEY_COMPRESSION_TYPE_NOT_SUPPORTED)
message = ResultMessage('')
return GetResult(ResultStatus(ret_value), reason, message)
if key_wrapping_specification is not None:
self.logger.debug('key wrapping specification is not None')
reason = ResultReason(ResultReasonEnum.FEATURE_NOT_SUPPORTED)
message = ResultMessage('key wrapping is not currently supported')
return GetResult(ResultStatus(ret_value), reason, message)
self.logger.debug('retrieving object from repo')
managed_object, _ = self.repo.get(uuid.value)
if managed_object is None:
self.logger.debug('object not found in repo')
reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
message = ResultMessage('')
return GetResult(ResultStatus(ret_value), reason, message)
# currently only symmetric keys are supported, fix this in future
object_type = ObjectType(OT.SYMMETRIC_KEY)
ret_value = RS.SUCCESS
return GetResult(ResultStatus(ret_value),
object_type=object_type,
uuid=uuid,
secret=managed_object)
def destroy(self, uuid):
self.logger.debug('destroy() called')
ret_value = RS.OPERATION_FAILED
if uuid is None or not hasattr(uuid, 'value'):
self.logger.debug('no uuid provided')
reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
message = ResultMessage('')
return DestroyResult(ResultStatus(ret_value), reason, message)
msg = 'deleting object from repo: {0}'.format(uuid)
self.logger.debug(msg)
if not self.repo.delete(uuid.value):
self.logger.debug('repo did not find and delete managed object')
reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
message = ResultMessage('')
return DestroyResult(ResultStatus(ret_value), reason, message)
ret_value = RS.SUCCESS
return DestroyResult(ResultStatus(ret_value), uuid=uuid)
def _validate_req_field(self, attrs, name, expected, msg, required=True):
self.logger.debug('Validating attribute %s' % name)
seen = False
found_attr = None
for attr in attrs:
if self._validate_field(attr, name, expected, msg):
if seen:
# TODO check what spec says to do on this
msg = 'duplicate attribute: %s' % name
self.logger.debug(msg)
result = self._get_duplicate_attribute_result(name)
raise InvalidFieldException(result)
seen = True
found_attr = attr
if required and not seen:
result = self._get_missing_field_result(name)
raise InvalidFieldException(result)
return found_attr
def _validate_field(self, attr, name, expected, msg):
if attr.attribute_name.value == name:
self.logger.debug('validating attribute %s' % name)
if not expected or attr.attribute_value.value in expected:
self.logger.debug('attribute validated')
return True
else:
self.logger.debug('attribute not validated')
result = self._get_invalid_field_result(msg)
raise InvalidFieldException(result)
else:
return False
def _get_invalid_field_result(self, msg):
status = ResultStatus(RS.OPERATION_FAILED)
reason = ResultReason(ResultReasonEnum.INVALID_FIELD)
message = ResultMessage(msg)
return OperationResult(status, reason, message)
def _get_missing_field_result(self, name):
msg = '%s not supplied' % name
self.logger.debug(msg)
status = ResultStatus(RS.OPERATION_FAILED)
reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
message = ResultMessage(msg)
return OperationResult(status, reason, message)
def _get_duplicate_attribute_result(self, name):
msg = '%s supplied multiple times' % name
self.logger.debug(msg)
status = ResultStatus(RS.OPERATION_FAILED)
reason = ResultReason(ResultReasonEnum.INDEX_OUT_OF_BOUNDS)
message = ResultMessage(msg)
return OperationResult(status, reason, message)
def _gen_symmetric_key(self, bit_length, crypto_alg):
key_format_type = KeyBlock.KeyFormatType(KeyFormatTypeEnum.RAW)
key_material = RawKey(bytearray(os.urandom(bit_length/8)))
key_value = KeyValueStruct(key_format_type, key_material)
crypto_length = CryptographicLength(bit_length)
key_block = KeyBlock(key_format_type, None, key_value, crypto_alg,
crypto_length, None)
return SymmetricKey(key_block)
def _save(self, key, attributes):
s_uuid = self.repo.save(key, attributes)
self.logger.debug('creating object with uuid = %s' % s_uuid)
attribute_type = AT.UNIQUE_IDENTIFIER
attribute = self.attribute_factory.create_attribute(attribute_type,
s_uuid)
attributes.append(attribute)
# Calling update to also store the UUID
self.repo.update(s_uuid, key, attributes)
return s_uuid, attribute
def _get_key_block_attributes(self, key_block):
self.logger.debug('getting all key attributes from key block')
attributes = []
if key_block.cryptographic_algorithm is not None:
self.logger.debug('crypto_alg set on key block')
self.logger.debug('adding crypto algorithm attribute')
at = AT.CRYPTOGRAPHIC_ALGORITHM
alg = key_block.cryptographic_algorithm.enum
attributes.append(self.attribute_factory.create_attribute(at, alg))
if key_block.cryptographic_length is not None:
self.logger.debug('crypto_length set on key block')
self.logger.debug('adding crypto length attribute')
at = AT.CRYPTOGRAPHIC_LENGTH
len = key_block.cryptographic_length.value
attributes.append(self.attribute_factory.create_attribute(at, len))
self.logger.debug('getting key value attributes')
if key_block.key_wrapping_data is not None:
self.logger.debug('no wrapping data so key value is struct')
kv = key_block.key_value
if isinstance(kv, KeyValue):
kv = key_block.key_value
if isinstance(kv, KeyValueStruct):
if kv.attributes is not None:
self.logger.debug('adding the key value struct attributes')
attributes.extend(kv.attributes)
return attributes
class InvalidFieldException(Exception):
def __init__(self, result):
super(self.__class__, self).__init__()
self.result = result

97
kmip/core/utils.py Normal file
View File

@ -0,0 +1,97 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from binascii import hexlify
from kmip.core.errors import ErrorStrings
def bit_length(num):
s = bin(num)
s = s.lstrip('0b')
return len(s)
def count_bytes(num):
bits = bit_length(num)
num_bytes = bits / 8
if bits == 0 or bits % 8:
num_bytes += 1
return num_bytes
def print_bytearray(array):
sbuffer = hexlify_bytearray(array)
print 'buffer: {0}'.format(sbuffer)
def hexlify_bytearray(array):
sbuffer = bytes(array[0:])
return hexlify(sbuffer)
def is_stream_empty(stream):
if len(stream.peek(1)) > 0:
return False
else:
return True
def build_er_error(class_object, descriptor, expected, received,
attribute=None):
msg = ErrorStrings.BAD_EXP_RECV
class_string = ''
if attribute is None:
class_string = '{0}'.format(class_object.__name__)
else:
class_string = '{0}.{1}'.format(class_object.__name__, attribute)
return msg.format(class_string, descriptor, expected, received)
class BytearrayStream(object):
def __init__(self, data=None):
if data is None:
self.buffer = bytearray()
else:
self.buffer = bytearray(data)
def read(self, n=None):
if n is None:
return str(self.buffer[0:])
length = len(self.buffer)
if n > length:
n = length
data = self.buffer[0:n]
for _ in xrange(n):
self.buffer.pop(0)
return str(data)
def peek(self, n=None):
length = len(self.buffer)
if n is None or n > length:
n = length
return str(self.buffer[0:n])
def write(self, b):
prev_bytes = len(self.buffer)
self.buffer.extend(b)
return len(self.buffer) - prev_bytes
def length(self):
return len(self.buffer)

14
kmip/demos/__init__.py Normal file
View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

69
kmip/demos/create.py Normal file
View File

@ -0,0 +1,69 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import AttributeType
from kmip.core.enums import CredentialType
from kmip.core.enums import ObjectType
from kmip.core.enums import CryptographicAlgorithm
from kmip.core.enums import CryptographicUsageMask
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.factories.credentials import CredentialFactory
from kmip.core.objects import TemplateAttribute
from kmip.services.kmip_client import KMIPProxy
import logging
import os
if __name__ == '__main__':
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
logging.config.fileConfig(f_log)
logger = logging.getLogger(__name__)
attribute_factory = AttributeFactory()
credential_factory = CredentialFactory()
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = credential_factory.create_credential(credential_type,
credential_value)
client = KMIPProxy()
client.open()
object_type = ObjectType.SYMMETRIC_KEY
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
algorithm = attribute_factory.create_attribute(attribute_type,
CryptographicAlgorithm.AES)
mask_flags = [CryptographicUsageMask.ENCRYPT,
CryptographicUsageMask.DECRYPT]
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
usage_mask = attribute_factory.create_attribute(attribute_type,
mask_flags)
attributes = [algorithm, usage_mask]
template_attribute = TemplateAttribute(attributes=attributes)
result = client.create(object_type, template_attribute,
credential)
client.close()
logger.debug('create() result status: {}'.format(
result.result_status.enum))
logger.debug('created object type: {}'.format(result.object_type.enum))
logger.debug('created UUID: {}'.format(result.uuid.value))
logger.debug('created template attribute: {}'.
format(result.template_attribute))

70
kmip/demos/destroy.py Normal file
View File

@ -0,0 +1,70 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import AttributeType
from kmip.core.enums import CredentialType
from kmip.core.enums import ObjectType
from kmip.core.enums import CryptographicAlgorithm
from kmip.core.enums import CryptographicUsageMask
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.factories.credentials import CredentialFactory
from kmip.core.objects import TemplateAttribute
from kmip.services.kmip_client import KMIPProxy
import logging
import os
if __name__ == '__main__':
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
logging.config.fileConfig(f_log)
logger = logging.getLogger(__name__)
attribute_factory = AttributeFactory()
credential_factory = CredentialFactory()
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = credential_factory.create_credential(credential_type,
credential_value)
client = KMIPProxy()
client.open()
# Create a SYMMETRIC_KEY object
object_type = ObjectType.SYMMETRIC_KEY
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
algorithm = attribute_factory.create_attribute(attribute_type,
CryptographicAlgorithm.AES)
mask_flags = [CryptographicUsageMask.ENCRYPT,
CryptographicUsageMask.DECRYPT]
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
usage_mask = attribute_factory.create_attribute(attribute_type,
mask_flags)
attributes = [algorithm, usage_mask]
template_attribute = TemplateAttribute(attributes=attributes)
result = client.create(object_type, template_attribute,
credential)
uuid = result.uuid.value
# Destroy the SYMMETRIC_KEY object
result = client.destroy(uuid, credential)
client.close()
logger.debug('destroy() result status: {}'.format(
result.result_status.enum))
logger.debug('destroyed UUID: {}'.format(result.uuid.value))

69
kmip/demos/get.py Normal file
View File

@ -0,0 +1,69 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import AttributeType
from kmip.core.enums import CredentialType
from kmip.core.enums import ObjectType
from kmip.core.enums import CryptographicAlgorithm
from kmip.core.enums import CryptographicUsageMask
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.factories.credentials import CredentialFactory
from kmip.core.objects import TemplateAttribute
from kmip.services.kmip_client import KMIPProxy
import logging
import os
if __name__ == '__main__':
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
logging.config.fileConfig(f_log)
logger = logging.getLogger(__name__)
attribute_factory = AttributeFactory()
credential_factory = CredentialFactory()
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = credential_factory.create_credential(credential_type,
credential_value)
client = KMIPProxy()
client.open()
object_type = ObjectType.SYMMETRIC_KEY
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
algorithm = attribute_factory.create_attribute(attribute_type,
CryptographicAlgorithm.AES)
mask_flags = [CryptographicUsageMask.ENCRYPT,
CryptographicUsageMask.DECRYPT]
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
usage_mask = attribute_factory.create_attribute(attribute_type,
mask_flags)
attributes = [algorithm, usage_mask]
template_attribute = TemplateAttribute(attributes=attributes)
result = client.create(object_type, template_attribute,
credential)
uuid = result.uuid.value
result = client.get(uuid, credential)
client.close()
logger.debug('get() result status: {}'.format(result.result_status.enum))
logger.debug('retrieved object type: {}'.format(result.object_type.enum))
logger.debug('retrieved UUID: {}'.format(result.uuid.value))
logger.debug('retrieved secret: {}'.format(result.secret))

84
kmip/demos/register.py Normal file
View File

@ -0,0 +1,84 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.core.enums import AttributeType
from kmip.core.enums import CredentialType
from kmip.core.enums import CryptographicAlgorithm
from kmip.core.enums import CryptographicUsageMask
from kmip.core.enums import KeyFormatType
from kmip.core.enums import ObjectType
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.factories.credentials import CredentialFactory
from kmip.core.factories.secrets import SecretFactory
from kmip.core.objects import TemplateAttribute
from kmip.services.kmip_client import KMIPProxy
import logging
import os
if __name__ == '__main__':
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
logging.config.fileConfig(f_log)
logger = logging.getLogger(__name__)
attribute_factory = AttributeFactory()
credential_factory = CredentialFactory()
secret_factory = SecretFactory()
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = credential_factory.create_credential(credential_type,
credential_value)
client = KMIPProxy()
client.open()
object_type = ObjectType.SYMMETRIC_KEY
algorithm_value = CryptographicAlgorithm.AES
mask_flags = [CryptographicUsageMask.ENCRYPT,
CryptographicUsageMask.DECRYPT]
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
usage_mask = attribute_factory.create_attribute(attribute_type,
mask_flags)
attributes = [usage_mask]
template_attribute = TemplateAttribute(attributes=attributes)
secret_features = {}
key_format_type = KeyFormatType.RAW
secret_features.update([('key_format_type', key_format_type)])
# TODO (peter-hamilton) Replace with calls to crypto libraries
key_data = {'bytes': bytearray('\x00\x00\x00\x00\x00\x00\x00\x00'
'\x00\x00\x00\x00\x00\x00\x00\x00')}
secret_features.update([('key_value', key_data)])
secret_features.update([('cryptographic_algorithm', algorithm_value)])
secret_features.update([('cryptographic_length', 128)])
secret = secret_factory.create_secret(object_type, secret_features)
result = client.register(object_type, template_attribute, secret,
credential)
client.close()
logger.debug('register() result status: {}'.format(
result.result_status.enum))
logger.debug('registered UUID: {}'.format(result.uuid.value))
logger.debug('registered template attribute: {}'.
format(result.template_attribute))

View File

@ -1,29 +0,0 @@
#!/usr/bin/env python
# TODO insert license here
from transport.kmip import KMIP
from transport.kmip.ttypes import *
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
try:
transport = TSocket.TSocket('localhost', 9090)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = KMIP.Client(protocol)
transport.open()
print 'ping-client()'
client.create()
print 'register_mo-client()'
client.register_mo()
transport.close()
except Thrift.TException, tx:
print '%s' % (tx.message)

View File

@ -1,32 +0,0 @@
#!/usr/bin/env python
# TODO insert license here
from transport.kmip import KMIP
from transport.kmip.ttypes import *
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
class KMIPHandler:
def __init__(self):
pass
def create(self):
print 'create()'
def register_mo(self):
print 'register_mo()'
handler = KMIPHandler()
processor = KMIP.Processor(handler)
transport = TSocket.TServerSocket(port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
print 'Starting the KMIP server...'
server.serve()
print 'done.'

21
kmip/logconfig.ini Normal file
View File

@ -0,0 +1,21 @@
[loggers]
keys=root
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

14
kmip/services/__init__.py Normal file
View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,276 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from kmip.services.results import CreateResult
from kmip.services.results import GetResult
from kmip.services.results import DestroyResult
from kmip.services.results import RegisterResult
from kmip.core import attributes as attr
from kmip.core.enums import Operation as OperationEnum
from kmip.core import objects
from kmip.core.server import KMIP
from kmip.core.messages.contents import Authentication
from kmip.core.messages.contents import BatchCount
from kmip.core.messages.contents import ProtocolVersion
from kmip.core.messages.contents import Operation
from kmip.core.messages import messages
from kmip.core.messages import operations
from kmip.services.kmip_protocol import KMIPProtocol
from kmip.core.utils import BytearrayStream
from thrift.transport import TSocket
from thrift.transport import TTransport
import logging
import logging.config
class KMIPProxy(KMIP):
# TODO (peter-hamilton) Move these defaults into config
def __init__(self, hostname='127.0.0.1', port=5696):
super(self.__class__, self).__init__()
self.logger = logging.getLogger(__name__)
self.socket = TSocket.TSocket(hostname, port)
self.transport = TTransport.TBufferedTransport(self.socket)
self.protocol = KMIPProtocol(self.transport)
def open(self):
self.transport.open()
def close(self):
self.transport.close()
def create(self, object_type, template_attribute, credential=None):
object_type = attr.ObjectType(object_type)
return self._create(object_type=object_type,
template_attribute=template_attribute,
credential=credential)
def get(self, uuid=None, key_format_type=None, key_compression_type=None,
key_wrapping_specification=None, credential=None):
return self._get(unique_identifier=uuid, credential=credential)
def destroy(self, uuid, credential=None):
return self._destroy(unique_identifier=uuid,
credential=credential)
def register(self, object_type, template_attribute, secret,
credential=None):
object_type = attr.ObjectType(object_type)
return self._register(object_type=object_type,
template_attribute=template_attribute,
secret=secret,
credential=credential)
def _create(self,
object_type=None,
template_attribute=None,
credential=None):
operation = Operation(OperationEnum.CREATE)
if object_type is None:
raise ValueError('object_type cannot be None')
req_pl = operations.CreateRequestPayload(
object_type=object_type,
template_attribute=template_attribute)
batch_item = messages.RequestBatchItem(operation=operation,
request_payload=req_pl)
message = self._build_request_message(credential, [batch_item])
self._send_message(message)
message = messages.ResponseMessage()
data = self._receive_message()
message.read(data)
batch_items = message.batch_items
batch_item = batch_items[0]
payload = batch_item.response_payload
if payload is None:
payload_unique_identifier = None
payload_template_attribute = None
payload_object_type = None
else:
payload_unique_identifier = payload.unique_identifier
payload_template_attribute = payload.template_attribute
payload_object_type = payload.object_type
result = CreateResult(batch_item.result_status,
batch_item.result_reason,
batch_item.result_message,
payload_object_type,
payload_unique_identifier,
payload_template_attribute)
return result
def _get(self,
unique_identifier=None,
key_format_type=None,
key_compression_type=None,
key_wrapping_specification=None,
credential=None):
operation = Operation(OperationEnum.GET)
uuid = None
kft = None
kct = None
kws = None
if unique_identifier is not None:
uuid = attr.UniqueIdentifier(unique_identifier)
if key_format_type is not None:
kft = operations.GetRequestPayload.KeyFormatType(key_format_type)
if key_compression_type is not None:
kct = key_compression_type
kct = operations.GetRequestPayload.KeyCompressionType(kct)
if key_wrapping_specification is not None:
kws = objects.KeyWrappingSpecification(key_wrapping_specification)
req_pl = operations.GetRequestPayload(unique_identifier=uuid,
key_format_type=kft,
key_compression_type=kct,
key_wrapping_specification=kws)
batch_item = messages.RequestBatchItem(operation=operation,
request_payload=req_pl)
message = self._build_request_message(credential, [batch_item])
self._send_message(message)
message = messages.ResponseMessage()
data = self._receive_message()
message.read(data)
batch_items = message.batch_items
batch_item = batch_items[0]
payload = batch_item.response_payload
if payload is None:
payload_unique_identifier = None
payload_object_type = None
payload_secret = None
else:
payload_unique_identifier = payload.unique_identifier
payload_object_type = payload.object_type
payload_secret = payload.secret
result = GetResult(batch_item.result_status,
batch_item.result_reason,
batch_item.result_message,
payload_object_type,
payload_unique_identifier,
payload_secret)
return result
def _destroy(self,
unique_identifier=None,
credential=None):
operation = Operation(OperationEnum.DESTROY)
uuid = None
if unique_identifier is not None:
uuid = attr.UniqueIdentifier(unique_identifier)
payload = operations.DestroyRequestPayload(unique_identifier=uuid)
batch_item = messages.RequestBatchItem(operation=operation,
request_payload=payload)
message = self._build_request_message(credential, [batch_item])
self._send_message(message)
message = messages.ResponseMessage()
data = self._receive_message()
message.read(data)
batch_items = message.batch_items
batch_item = batch_items[0]
payload = batch_item.response_payload
if payload is None:
payload_unique_identifier = None
else:
payload_unique_identifier = payload.unique_identifier
result = DestroyResult(batch_item.result_status,
batch_item.result_reason,
batch_item.result_message,
payload_unique_identifier)
return result
def _register(self,
object_type=None,
template_attribute=None,
secret=None,
credential=None):
operation = Operation(OperationEnum.REGISTER)
if object_type is None:
raise ValueError('object_type cannot be None')
req_pl = operations.RegisterRequestPayload(
object_type=object_type,
template_attribute=template_attribute,
secret=secret)
batch_item = messages.RequestBatchItem(operation=operation,
request_payload=req_pl)
message = self._build_request_message(credential, [batch_item])
self._send_message(message)
message = messages.ResponseMessage()
data = self._receive_message()
message.read(data)
batch_items = message.batch_items
batch_item = batch_items[0]
payload = batch_item.response_payload
if payload is None:
payload_unique_identifier = None
payload_template_attribute = None
else:
payload_unique_identifier = payload.unique_identifier
payload_template_attribute = payload.template_attribute
result = RegisterResult(batch_item.result_status,
batch_item.result_reason,
batch_item.result_message,
payload_unique_identifier,
payload_template_attribute)
return result
def _build_request_message(self, credential, batch_items):
protocol_version = ProtocolVersion.create(1, 1)
authentication = None
if credential is not None:
authentication = Authentication(credential)
batch_count = BatchCount(len(batch_items))
req_header = messages.RequestHeader(protocol_version=protocol_version,
authentication=authentication,
batch_count=batch_count)
return messages.RequestMessage(request_header=req_header,
batch_items=batch_items)
def _send_message(self, message):
stream = BytearrayStream()
message.write(stream)
self.protocol.write(stream.buffer)
def _receive_message(self):
return self.protocol.read()

View File

@ -0,0 +1,50 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from struct import unpack
from thrift.protocol.TProtocol import TProtocolBase
import binascii
import logging
from kmip.core.utils import BytearrayStream
class KMIPProtocol(TProtocolBase):
HEADER_SIZE = 8
def __init__(self, trans, buffer_size=1024):
TProtocolBase.__init__(self, trans)
self.logger = logging.getLogger(__name__)
def write(self, data):
if len(data) > 0:
sbuffer = bytes(data)
self.logger.debug('buffer: {0}'.format(binascii.hexlify(sbuffer)))
self.trans.write(sbuffer)
self.trans.flush()
def read(self):
header = self.trans.readAll(self.HEADER_SIZE)
msg_size = unpack('!I', header[4:])[0]
payload = self.trans.readAll(msg_size)
return BytearrayStream(header + payload)
class KMIPProtocolFactory(object):
def getProtocol(self, trans):
return KMIPProtocol(trans)

253
kmip/services/kmip_server.py Executable file
View File

@ -0,0 +1,253 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
import time
from thrift.Thrift import TProcessor
from kmip.core.messages.messages import RequestMessage
from kmip.core.messages.messages import ResponseMessage
from kmip.core.messages.messages import ResponseBatchItem
from kmip.core.messages.messages import ResponseHeader
from kmip.core.messages.contents import AsynchronousIndicator
from kmip.core.messages.contents import BatchErrorContinuationOption
from kmip.core.messages.contents import BatchCount
from kmip.core.messages.contents import TimeStamp
from kmip.core.primitives import Base
from kmip.core.messages.operations import CreateResponsePayload
from kmip.core.messages.operations import GetResponsePayload
from kmip.core.messages.operations import DestroyResponsePayload
from kmip.core.messages.operations import RegisterResponsePayload
from kmip.core.enums import Operation
from kmip.core.enums import ResultStatus as RS
from kmip.core.enums import Tags
from kmip.core.enums import BatchErrorContinuationOption as BECO
from kmip.core.utils import BytearrayStream
class Processor(TProcessor):
def __init__(self, handler):
self._handler = handler
def process(self, istream, ostream):
stream = istream.read()
if Base.is_tag_next(Tags.REQUEST_MESSAGE, stream):
message = RequestMessage()
message.read(stream)
result = self._process_request(message)
tstream = BytearrayStream()
result.write(tstream)
ostream.write(tstream.buffer)
elif Base.is_tag_next(Tags.RESPONSE_MESSAGE, stream):
message = ResponseMessage()
message.read(stream)
self._process_response(message)
else:
raise ValueError('Processing error: stream contains unknown'
'message type')
def _process_request(self, message):
header = message.request_header
protocol_version = header.protocol_version
# maximum_response_size = header.maximum_response_size
asynchronous_indicator = header.asynchronous_indicator
# authentication = header.authentication
batch_error_cont_option = header.batch_error_cont_option
# batch_order_option = header.batch_order_option
# time_stamp = header.time_stamp
request_batch_count = header.batch_count.value
# TODO (peter-hamilton) Log receipt of message with time stamp
if asynchronous_indicator is None:
asynchronous_indicator = AsynchronousIndicator(False)
if batch_error_cont_option is None:
batch_error_cont_option = BatchErrorContinuationOption(BECO.STOP)
request_batch_items = message.batch_items
response_batch_items = []
for i in xrange(request_batch_count):
request_batch_item = request_batch_items[i]
failure_occurred = False
operation = request_batch_item.operation
ubi_id = request_batch_item.unique_batch_item_id
payload = request_batch_item.request_payload
message_extension = request_batch_item.message_extension
result = self._process_operation(operation, payload)
result_status = result[0]
result_reason = result[1]
result_message = result[2]
asyn_cv = None
response_payload = None
message_extension = None
if result_status.enum is RS.SUCCESS:
response_payload = result[3]
elif result_status.enum is RS.OPERATION_FAILED:
failure_occurred = True
result_reason = result[1]
elif result_status.enum is RS.OPERATION_PENDING:
# TODO (peter-hamilton) Need to add a way to track async
# TODO (peter-hamilton) operations.
asyn_cv = '\x00'
elif result_status.enum is RS.OPERATION_UNDONE:
result_reason = result[1]
else:
msg = 'Unrecognized operation result status: {}'
raise RuntimeError(msg.format(result_status))
resp_bi = ResponseBatchItem(operation=operation,
unique_batch_item_id=ubi_id,
result_status=result_status,
result_reason=result_reason,
result_message=result_message,
async_correlation_value=asyn_cv,
response_payload=response_payload,
message_extension=message_extension)
response_batch_items.append(resp_bi)
if failure_occurred:
if batch_error_cont_option.enum is BECO.STOP:
break
elif batch_error_cont_option.enum is BECO.UNDO:
# TODO (peter-hamilton) Tell client to undo operations.
# TODO (peter-hamilton) Unclear what response should be.
break
elif batch_error_cont_option.enum is BECO.CONTINUE:
continue
else:
msg = 'Unrecognized batch error continuation option: {}'
raise RuntimeError(msg.format(batch_error_cont_option))
response_batch_count = BatchCount(len(response_batch_items))
response_time_stamp = TimeStamp(int(time.time()))
response_header = ResponseHeader(protocol_version=protocol_version,
time_stamp=response_time_stamp,
batch_count=response_batch_count)
response_message = ResponseMessage(response_header=response_header,
batch_items=response_batch_items)
return response_message
def _process_response(self, message):
raise NotImplementedError()
def _process_operation(self, operation, payload):
op = operation.enum
if op is Operation.CREATE:
return self._process_create_request(payload)
elif op is Operation.GET:
return self._process_get_request(payload)
elif op is Operation.DESTROY:
return self._process_destroy_request(payload)
elif op is Operation.REGISTER:
return self._process_register_request(payload)
else:
raise NotImplementedError()
def _process_create_request(self, payload):
object_type = payload.object_type
template_attribute = payload.template_attribute
result = self._handler.create(object_type, template_attribute)
result_status = result.result_status
result_reason = result.result_reason
result_message = result.result_message
created_type = result.object_type
uuid = result.uuid
template_attribute = result.template_attribute
resp_pl = CreateResponsePayload(object_type=created_type,
unique_identifier=uuid,
template_attribute=template_attribute)
return (result_status, result_reason, result_message, resp_pl)
def _process_get_request(self, payload):
uuid = None
kft = None
kct = None
unique_identifier = payload.unique_identifier
key_format_type = payload.key_format_type
key_compression_type = payload.key_compression_type
key_wrapping_specification = payload.key_wrapping_specification
if unique_identifier is not None:
uuid = unique_identifier
if key_format_type is not None:
kft = key_format_type
if key_compression_type is not None:
kct = key_compression_type
result = self._handler.get(uuid, kft, kct,
key_wrapping_specification)
result_status = result.result_status
result_reason = result.result_reason
result_message = result.result_message
retrieved_type = result.object_type
uuid = result.uuid
secret = result.secret
resp_pl = GetResponsePayload(object_type=retrieved_type,
unique_identifier=uuid,
secret=secret)
return (result_status, result_reason, result_message, resp_pl)
def _process_destroy_request(self, payload):
uuid = payload.unique_identifier
result = self._handler.destroy(uuid)
result_status = result.result_status
result_reason = result.result_reason
result_message = result.result_message
uuid = result.uuid
payload = DestroyResponsePayload(unique_identifier=uuid)
return (result_status, result_reason, result_message, payload)
def _process_register_request(self, payload):
object_type = payload.object_type
template_attribute = payload.template_attribute
secret = payload.secret
result = self._handler.register(object_type, template_attribute,
secret)
result_status = result.result_status
result_reason = result.result_reason
result_message = result.result_message
uuid = result.uuid
template_attr = result.template_attribute
resp_pl = RegisterResponsePayload(unique_identifier=uuid,
template_attribute=template_attr)
return (result_status, result_reason, result_message, resp_pl)

127
kmip/services/results.py Normal file
View File

@ -0,0 +1,127 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
class OperationResult(object):
def __init__(self,
result_status,
result_reason=None,
result_message=None):
self.result_status = result_status
if result_reason is not None:
self.result_reason = result_reason
else:
self.result_reason = None
if result_message is not None:
self.result_message = result_message
else:
self.result_message = None
class CreateResult(OperationResult):
def __init__(self,
result_status,
result_reason=None,
result_message=None,
object_type=None,
uuid=None,
template_attribute=None):
super(self.__class__, self).__init__(result_status,
result_reason,
result_message)
if object_type is not None:
self.object_type = object_type
else:
self.object_type = None
if uuid is not None:
self.uuid = uuid
else:
self.uuid = None
if template_attribute is not None:
self.template_attribute = template_attribute
else:
self.template_attribute = None
class RegisterResult(OperationResult):
def __init__(self,
result_status,
result_reason=None,
result_message=None,
uuid=None,
template_attribute=None):
super(self.__class__, self).__init__(result_status,
result_reason,
result_message)
if uuid is not None:
self.uuid = uuid
else:
self.uuid = None
if template_attribute is not None:
self.template_attribute = template_attribute
else:
self.template_attribute = None
class GetResult(OperationResult):
def __init__(self,
result_status,
result_reason=None,
result_message=None,
object_type=None,
uuid=None,
secret=None):
super(self.__class__, self).__init__(result_status,
result_reason,
result_message)
if object_type is not None:
self.object_type = object_type
else:
self.object_type = None
if uuid is not None:
self.uuid = uuid
else:
self.uuid = None
if secret is not None:
self.secret = secret
else:
self.secret = None
class DestroyResult(OperationResult):
def __init__(self,
result_status,
result_reason=None,
result_message=None,
uuid=None):
super(self.__class__, self).__init__(result_status,
result_reason,
result_message)
if uuid is not None:
self.uuid = uuid
else:
self.uuid = None

14
kmip/tests/__init__.py Normal file
View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,62 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from testtools import TestCase
from kmip.core.utils import BytearrayStream
class TestNameValue(TestCase):
def setUp(self):
super(TestNameValue, self).setUp()
self.stream = BytearrayStream()
def tearDown(self):
super(TestNameValue, self).tearDown()
def test_write_no_padding(self):
pass
def test_write_with_padding(self):
pass
def test_read_no_padding(self):
pass
def test_read_with_padding(self):
pass
class TestName(TestCase):
def setUp(self):
super(TestName, self).setUp()
self.stream = BytearrayStream()
def tearDown(self):
super(TestName, self).tearDown()
def test_minimum_write(self):
pass
def test_maximum_write(self):
pass
def test_minimum_read(self):
pass
def test_maximum_read(self):
pass

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,508 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from testtools import TestCase
from kmip.core.attributes import CryptographicAlgorithm
from kmip.core.attributes import CryptographicLength
from kmip.core.attributes import CryptographicUsageMask
from kmip.core.attributes import UniqueIdentifier
from kmip.core.attributes import ObjectType
from kmip.core.enums import AttributeType
from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum
from kmip.core.enums import CryptographicUsageMask as CryptoUsageMaskEnum
from kmip.core.enums import KeyCompressionType as KeyCompressionTypeEnum
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
from kmip.core.enums import ObjectType as ObjectTypeEnum
from kmip.core.enums import ResultReason
from kmip.core.enums import ResultStatus
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.keys import RawKey
from kmip.core.messages.contents import KeyCompressionType
from kmip.core.messages.contents import KeyFormatType
from kmip.core.objects import KeyBlock
from kmip.core.objects import KeyValueStruct
from kmip.core.objects import TemplateAttribute
from kmip.core.secrets import SymmetricKey
from kmip.core.server import KMIPImpl
class TestKMIPServer(TestCase):
def setUp(self):
super(TestKMIPServer, self).setUp()
self.kmip = KMIPImpl()
self.algorithm_name = CryptoAlgorithmEnum.AES
self.key_length = 256
self.key = bytearray(range(0, 32))
self.usage_mask = CryptoUsageMaskEnum.ENCRYPT.value |\
CryptoUsageMaskEnum.DECRYPT.value
def tearDown(self):
super(TestKMIPServer, self).tearDown()
def test_create(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
attributes = self._get_attrs()
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.create(obj_type, template_attribute)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
def test_create_no_length(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
attributes = self._get_attrs()[0:2]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.create(obj_type, template_attribute)
self.assertNotEqual(None, res, 'result is None')
attrs = res.template_attribute.attributes
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
self.assertTrue(self._check_attr_exists(attributes[2], attrs),
'length attribute not returned')
def test_create_no_alg(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
attributes = [self._get_attrs()[1]]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.create(obj_type, template_attribute)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
'result status did not return failed')
def test_create_no_usage_mask(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
attributes = [self._get_attrs()[0]]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.create(obj_type, template_attribute)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
'result status did not return failed')
def test_register(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
def test_register_attrs_in_key_value(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_algorithm = None
key.key_block.cryptographic_length = None
key.key_block.key_value.attributes = self._get_attrs()
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
def test_register_attrs_in_template(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_algorithm = None
key.key_block.cryptographic_length = None
key.key_block.key_value.attributes = []
attributes = self._get_attrs()
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
def test_register_no_alg(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_algorithm = None
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_register_alg_in_key_value_and_key_block(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.key_value.attributes = [self._get_alg_attr()]
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
res.result_reason.enum,
'result reason did not match')
def test_register_alg_in_template_and_key_block(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
attributes = [self._get_alg_attr()]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
res.result_reason.enum,
'result reason did not match')
def test_register_alg_in_template_and_key_value(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_algorithm = None
key.key_block.key_value.attributes = [self._get_alg_attr()]
attributes = [self._get_alg_attr()]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
res.result_reason.enum,
'result reason did not match')
def test_register_invalid_alg(self):
unsupported_algs = (CryptoAlgorithmEnum.RSA,
CryptoAlgorithmEnum.DSA,
CryptoAlgorithmEnum.ECDSA,
CryptoAlgorithmEnum.HMAC_SHA1,
CryptoAlgorithmEnum.HMAC_SHA224,
CryptoAlgorithmEnum.HMAC_SHA256,
CryptoAlgorithmEnum.HMAC_SHA384,
CryptoAlgorithmEnum.HMAC_SHA512,
CryptoAlgorithmEnum.HMAC_MD5,
CryptoAlgorithmEnum.DH,
CryptoAlgorithmEnum.ECDH,
CryptoAlgorithmEnum.ECMQV,
CryptoAlgorithmEnum.BLOWFISH,
CryptoAlgorithmEnum.CAMELLIA,
CryptoAlgorithmEnum.CAST5,
CryptoAlgorithmEnum.IDEA,
CryptoAlgorithmEnum.MARS,
CryptoAlgorithmEnum.RC2,
CryptoAlgorithmEnum.RC4,
CryptoAlgorithmEnum.RC5,
CryptoAlgorithmEnum.SKIPJACK,
CryptoAlgorithmEnum.TWOFISH)
for alg in unsupported_algs:
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_algorithm = CryptographicAlgorithm(alg)
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INVALID_FIELD,
res.result_reason.enum,
'result reason did not match')
def test_register_no_length(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_length = None
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_register_length_in_key_value_and_key_block(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.key_value.attributes = [self._get_length_attr()]
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
res.result_reason.enum,
'result reason did not match')
def test_register_length_in_template_and_key_block(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
attributes = [self._get_length_attr()]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
res.result_reason.enum,
'result reason did not match')
def test_register_length_in_template_and_key_value(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_length = None
key.key_block.key_value.attributes = [self._get_length_attr()]
attributes = [self._get_length_attr()]
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
res.result_reason.enum,
'result reason did not match')
def test_register_invalid_length(self):
unsupported_lens = (-1, 0, 2048, 5, 18)
for len in unsupported_lens:
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.cryptographic_length = CryptographicLength(len)
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INVALID_FIELD,
res.result_reason.enum,
'result reason did not match')
def test_register_no_usage_mask(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
key = self._get_symmetric_key()
key.key_block.key_value.attributes = []
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_register_no_object_type(self):
obj_type = None
key = self._get_symmetric_key()
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_register_unsupported_object_type(self):
unsupported_types = (ObjectTypeEnum.CERTIFICATE,
ObjectTypeEnum.PUBLIC_KEY,
ObjectTypeEnum.PRIVATE_KEY,
ObjectTypeEnum.SPLIT_KEY,
ObjectTypeEnum.TEMPLATE,
ObjectTypeEnum.SECRET_DATA,
ObjectTypeEnum.OPAQUE_DATA)
for unsupported_type in unsupported_types:
obj_type = ObjectType(unsupported_type)
key = self._get_symmetric_key()
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INVALID_FIELD,
res.result_reason.enum,
'result reason did not match')
def test_register_object_type_mismatch(self):
unsupported_types = (ObjectTypeEnum.CERTIFICATE,
ObjectTypeEnum.PUBLIC_KEY,
ObjectTypeEnum.PRIVATE_KEY,
ObjectTypeEnum.SPLIT_KEY,
ObjectTypeEnum.TEMPLATE,
ObjectTypeEnum.SECRET_DATA,
ObjectTypeEnum.OPAQUE_DATA)
for unsupported_type in unsupported_types:
obj_type = ObjectType(unsupported_type)
key = self._get_symmetric_key()
attributes = []
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.register(obj_type, template_attribute, key)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.INVALID_FIELD,
res.result_reason.enum,
'result reason did not match')
def test_get(self):
uuid = self._create()
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
res = self.kmip.get(uuid, key_format_type)
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
def test_get_no_key_format_type(self):
uuid = self._create()
res = self.kmip.get(uuid, None)
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
def test_get_unknown(self):
uuids = ('some random string', UniqueIdentifier('no key here'))
for uuid in uuids:
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
res = self.kmip.get(uuid, key_format_type)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_get_no_uuid(self):
self._create()
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
res = self.kmip.get(None, key_format_type)
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
'result status did not return failed')
def test_get_with_key_compression(self):
uuid = self._create()
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
key_compression = KeyCompressionType(KeyCompressionTypeEnum.
EC_PUBLIC_KEY_TYPE_UNCOMPRESSED)
res = self.kmip.get(uuid, key_format_type, key_compression)
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.KEY_COMPRESSION_TYPE_NOT_SUPPORTED,
res.result_reason.enum,
'result reason did not match')
def test_destroy(self):
uuid = self._create()
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
res = self.kmip.get(uuid, key_format_type)
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
res = self.kmip.destroy(uuid)
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
res = self.kmip.destroy(uuid)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_destroy_no_uuid(self):
res = self.kmip.destroy(None)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def test_destroy_unknown(self):
uuids = ('some random string', UniqueIdentifier('no key here'))
for uuid in uuids:
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
res = self.kmip.get(uuid, key_format_type)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
res = self.kmip.destroy(uuid)
self.assertEqual(ResultStatus.OPERATION_FAILED,
res.result_status.enum,
'result status did not return failed')
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
res.result_reason.enum,
'result reason did not match')
def _create(self):
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
attributes = self._get_attrs()
template_attribute = TemplateAttribute(attributes=attributes)
res = self.kmip.create(obj_type, template_attribute)
self.assertNotEqual(None, res, 'result is None')
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
'result status did not return success')
return res.uuid
def _get_symmetric_key(self):
# only need usage attribute
attrs = [self._get_attrs()[1]]
key_format_type = KeyBlock.KeyFormatType(KeyFormatTypeEnum.RAW)
key_material = RawKey(self.key)
key_value = KeyValueStruct(key_format_type, key_material, attrs)
crypto_alg = CryptographicAlgorithm(self.algorithm_name)
crypto_length = CryptographicLength(self.key_length)
usage = CryptographicUsageMask(self.usage_mask)
key_block = KeyBlock(key_format_type, None, key_value, crypto_alg,
crypto_length, usage)
return SymmetricKey(key_block)
def _get_attrs(self):
attr_factory = AttributeFactory()
algorithm = self._get_alg_attr(self.algorithm_name)
length = self._get_length_attr(self.key_length)
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
mask_flags = [CryptoUsageMaskEnum.ENCRYPT,
CryptoUsageMaskEnum.DECRYPT]
usage_mask = attr_factory.create_attribute(attribute_type,
mask_flags)
return [algorithm, usage_mask, length]
def _get_alg_attr(self, alg=None):
if alg is None:
alg = self.algorithm_name
attr_factory = AttributeFactory()
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
return attr_factory.create_attribute(attribute_type, alg)
def _get_length_attr(self, length=None):
if length is None:
length = self.key_length
attr_factory = AttributeFactory()
attribute_type = AttributeType.CRYPTOGRAPHIC_LENGTH
return attr_factory.create_attribute(attribute_type, length)
def _check_attr_exists(self, attr_expected, attributes):
for attribute in attributes:
if attribute.attribute_name.value ==\
attr_expected.attribute_name.value:
return attribute.attribute_value.value ==\
attr_expected.attribute_value.value
return False

View File

@ -0,0 +1,134 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from testtools import TestCase
from kmip.core.errors import ErrorStrings
from kmip.core import utils
class TestUtils(TestCase):
def setUp(self):
super(TestUtils, self).setUp()
def tearDown(self):
super(TestUtils, self).tearDown()
def test_count_bytes(self):
num = 65535
bytes_exp = 2
bytes_obs = utils.count_bytes(num)
self.assertEqual(bytes_exp, bytes_obs,
'Value {0} requires {1} bytes to encode, '
'received {2} byte(s)'.format(num, bytes_exp,
bytes_obs))
def test_count_bytes_overflow(self):
num = 65536
bytes_exp = 3
bytes_obs = utils.count_bytes(num)
self.assertEqual(bytes_exp, bytes_obs,
'Value {0} requires {1} bytes to encode, '
'received {2} bytes'.format(num, bytes_exp,
bytes_obs))
def test_count_bytes_zero(self):
num = 0
bytes_exp = 1
bytes_obs = utils.count_bytes(num)
self.assertEqual(bytes_exp, bytes_obs,
'Value {0} requires {1} bytes to encode, '
'received {2} byte(s)'.format(num, bytes_exp,
bytes_obs))
class TestBytearrayStream(TestCase):
def setUp(self):
super(TestBytearrayStream, self).setUp()
self.stream = utils.BytearrayStream()
self.bad_type = ErrorStrings.BAD_EXP_RECV.format('BytearrayStream.{0}',
'type', '{1}', '{2}')
self.bad_len = ErrorStrings.BAD_EXP_RECV.format('BytearrayStream.{0}',
'length', '{1}', '{2}')
self.bad_val = ErrorStrings.BAD_EXP_RECV.format('BytearrayStream.{0}',
'value', '{1}', '{2}')
def tearDown(self):
super(TestBytearrayStream, self).tearDown()
def test_init(self):
value = '\x00'
b = utils.BytearrayStream(value)
buf_type = type(b.buffer)
msg = self.bad_type.format('buffer', bytearray, buf_type)
self.assertIsInstance(b.buffer, bytearray,
msg.format(bytearray, type(b.buffer)))
length = len(b.buffer)
msg = self.bad_len.format('buffer', 1, length)
self.assertEqual(1, length, msg)
content = str(b.buffer)
msg = self.bad_val.format('buffer', value, content)
self.assertEqual(value, content, msg)
def test_init_unset(self):
b = utils.BytearrayStream()
buf_type = type(b.buffer)
msg = self.bad_type.format('buffer', bytearray, buf_type)
self.assertIsInstance(b.buffer, bytearray,
msg.format(bytearray, type(b.buffer)))
length = len(b.buffer)
msg = self.bad_len.format('buffer', 0, length)
self.assertEqual(0, length, msg)
def test_read(self):
# TODO (peter-hamilton) Finish implementation.
self.skip('')
def test_write(self):
# TODO (peter-hamilton) Finish implementation.
self.skip('')
def test_peek(self):
# TODO (peter-hamilton) Finish implementation.
value = ('\x00\x01\x02\x03')
expected = value
b = expected
expected = b
b = utils.BytearrayStream(value)
def test_peek_overflow(self):
# TODO (peter-hamilton) Finish implementation.
self.skip('')
def test_peek_empty(self):
# TODO (peter-hamilton) Finish implementation.
self.skip('')
def test_peek_none(self):
# TODO (peter-hamilton) Finish implementation.
self.skip('')
def test_length(self):
# TODO (peter-hamilton) Finish implementation.
self.skip('')

View File

@ -0,0 +1,14 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.

View File

@ -0,0 +1,385 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# 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
#
# http://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.
from testtools import TestCase
from subprocess import Popen
import os
import sys
import time
from kmip.core.enums import AttributeType
from kmip.core.enums import CredentialType
from kmip.core.enums import CryptographicAlgorithm
from kmip.core.enums import CryptographicUsageMask
from kmip.core.enums import ObjectType
from kmip.core.enums import KeyFormatType
from kmip.core.enums import ResultStatus
from kmip.core.enums import ResultReason
from kmip.core.errors import KMIPServerSuicideError
from kmip.core.errors import KMIPServerZombieError
from kmip.core.factories.attributes import AttributeFactory
from kmip.core.factories.credentials import CredentialFactory
from kmip.core.factories.secrets import SecretFactory
from kmip.core.objects import Attribute
from kmip.core.objects import TemplateAttribute
from kmip.core.secrets import SymmetricKey
from kmip.services.kmip_client import KMIPProxy
import kmip.core.utils as utils
class TestKMIPClient(TestCase):
STARTUP_TIME = 1.0
SHUTDOWN_TIME = 0.1
KMIP_PORT = 9090
def setUp(self):
super(TestKMIPClient, self).setUp()
self.attr_factory = AttributeFactory()
self.cred_factory = CredentialFactory()
self.secret_factory = SecretFactory()
# Set up the KMIP server process
path = os.path.join(os.path.dirname(__file__), os.path.pardir,
os.path.pardir, os.path.pardir, 'bin',
'run_server.py')
self.server = Popen(['python', '{0}'.format(path), '-p',
'{0}'.format(self.KMIP_PORT)], stderr=sys.stdout)
time.sleep(self.STARTUP_TIME)
if self.server.poll() is not None:
raise KMIPServerSuicideError(self.server.pid)
# Set up and open the client proxy; shutdown the server if open fails
try:
self.client = KMIPProxy(port=self.KMIP_PORT)
self.client.open()
except Exception, e:
self._shutdown_server()
raise e
def tearDown(self):
super(TestKMIPClient, self).tearDown()
# Close the client proxy and shutdown the server
self.client.close()
self._shutdown_server()
def test_create(self):
result = self._create_symmetric_key()
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.SUCCESS)
self._check_object_type(result.object_type.enum, ObjectType,
ObjectType.SYMMETRIC_KEY)
self._check_uuid(result.uuid.value, str)
# Check the template attribute type
self._check_template_attribute(result.template_attribute,
TemplateAttribute, 2,
[[str, 'Cryptographic Length', int,
256],
[str, 'Unique Identifier', str,
None]])
def test_get(self):
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = self.cred_factory.create_credential(credential_type,
credential_value)
result = self._create_symmetric_key()
uuid = result.uuid.value
result = self.client.get(uuid, credential)
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.SUCCESS)
self._check_object_type(result.object_type.enum, ObjectType,
ObjectType.SYMMETRIC_KEY)
self._check_uuid(result.uuid.value, str)
# Check the secret type
secret = result.secret
expected = SymmetricKey
message = utils.build_er_error(result.__class__, 'type', expected,
secret, 'secret')
self.assertIsInstance(secret, expected, message)
def test_destroy(self):
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = self.cred_factory.create_credential(credential_type,
credential_value)
result = self._create_symmetric_key()
uuid = result.uuid.value
# Verify the secret was created
result = self.client.get(uuid, credential)
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.SUCCESS)
self._check_object_type(result.object_type.enum, ObjectType,
ObjectType.SYMMETRIC_KEY)
self._check_uuid(result.uuid.value, str)
secret = result.secret
expected = SymmetricKey
message = utils.build_er_error(result.__class__, 'type', expected,
secret, 'secret')
self.assertIsInstance(secret, expected, message)
# Destroy the SYMMETRIC_KEY object
result = self.client.destroy(uuid, credential)
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.SUCCESS)
self._check_uuid(result.uuid.value, str)
# Verify the secret was destroyed
result = self.client.get(uuid, credential)
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.OPERATION_FAILED)
expected = ResultReason
observed = type(result.result_reason.enum)
message = utils.build_er_error(result.result_reason.__class__, 'type',
expected, observed)
self.assertEqual(expected, observed, message)
expected = ResultReason.ITEM_NOT_FOUND
observed = result.result_reason.enum
message = utils.build_er_error(result.result_reason.__class__,
'value', expected, observed)
self.assertEqual(expected, observed, message)
def test_register(self):
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = self.cred_factory.create_credential(credential_type,
credential_value)
object_type = ObjectType.SYMMETRIC_KEY
algorithm_value = CryptographicAlgorithm.AES
mask_flags = [CryptographicUsageMask.ENCRYPT,
CryptographicUsageMask.DECRYPT]
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
usage_mask = self.attr_factory.create_attribute(attribute_type,
mask_flags)
attributes = [usage_mask]
template_attribute = TemplateAttribute(attributes=attributes)
secret_features = {}
key_format_type = KeyFormatType.RAW
secret_features.update([('key_format_type', key_format_type)])
key_data = {'bytes': bytearray('\x00\x00\x00\x00\x00\x00\x00\x00'
'\x00\x00\x00\x00\x00\x00\x00\x00')}
secret_features.update([('key_value', key_data)])
secret_features.update([('cryptographic_algorithm', algorithm_value)])
secret_features.update([('cryptographic_length', 128)])
secret = self.secret_factory.create_secret(object_type,
secret_features)
result = self.client.register(object_type, template_attribute, secret,
credential)
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.SUCCESS)
self._check_uuid(result.uuid.value, str)
# Check the template attribute type
self._check_template_attribute(result.template_attribute,
TemplateAttribute, 1,
[[str, 'Unique Identifier', str,
None]])
# Check that the returned key bytes match what was provided
uuid = result.uuid.value
result = self.client.get(uuid, credential)
self._check_result_status(result.result_status.enum, ResultStatus,
ResultStatus.SUCCESS)
self._check_object_type(result.object_type.enum, ObjectType,
ObjectType.SYMMETRIC_KEY)
self._check_uuid(result.uuid.value, str)
# Check the secret type
secret = result.secret
expected = SymmetricKey
message = utils.build_er_error(result.__class__, 'type', expected,
secret, 'secret')
self.assertIsInstance(secret, expected, message)
key_block = result.secret.key_block
key_value = key_block.key_value
key_material = key_value.key_value.key_material
expected = key_data.get('bytes')
observed = key_material.value
message = utils.build_er_error(key_material.__class__, 'value',
expected, observed, 'value')
self.assertEqual(expected, observed, message)
def _shutdown_server(self):
if self.server.poll() is not None:
return
else:
# Terminate the server process. If it resists, kill it.
pid = self.server.pid
self.server.terminate()
time.sleep(self.SHUTDOWN_TIME)
if self.server.poll() is None:
raise KMIPServerZombieError(pid)
def _create_symmetric_key(self):
credential_type = CredentialType.USERNAME_AND_PASSWORD
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
credential = self.cred_factory.create_credential(credential_type,
credential_value)
object_type = ObjectType.SYMMETRIC_KEY
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
algorithm = self.attr_factory.create_attribute(
attribute_type,
CryptographicAlgorithm.AES)
mask_flags = [CryptographicUsageMask.ENCRYPT,
CryptographicUsageMask.DECRYPT]
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
usage_mask = self.attr_factory.create_attribute(attribute_type,
mask_flags)
attributes = [algorithm, usage_mask]
template_attribute = TemplateAttribute(attributes=attributes)
return self.client.create(object_type, template_attribute,
credential)
def _check_result_status(self, result_status, result_status_type,
result_status_value):
# Error check the result status type and value
expected = result_status_type
message = utils.build_er_error(result_status_type, 'type', expected,
result_status)
self.assertIsInstance(result_status, expected, message)
expected = result_status_value
message = utils.build_er_error(result_status_type, 'value', expected,
result_status)
self.assertEqual(expected, result_status, message)
def _check_uuid(self, uuid, uuid_type):
# Error check the UUID type and value
not_expected = None
message = utils.build_er_error(uuid_type, 'type',
'not {0}'.format(not_expected), uuid)
self.assertNotEqual(not_expected, uuid, message)
expected = uuid_type
message = utils.build_er_error(uuid_type, 'type', expected, uuid)
self.assertEqual(expected, type(uuid), message)
def _check_object_type(self, object_type, object_type_type,
object_type_value):
# Error check the object type type and value
expected = object_type_type
message = utils.build_er_error(object_type_type, 'type', expected,
object_type)
self.assertIsInstance(object_type, expected, message)
expected = object_type_value
message = utils.build_er_error(object_type_type, 'value', expected,
object_type)
self.assertEqual(expected, object_type, message)
def _check_template_attribute(self, template_attribute,
template_attribute_type, num_attributes,
attribute_features):
# Error check the template attribute type
expected = template_attribute_type
message = utils.build_er_error(template_attribute.__class__, 'type',
expected, template_attribute)
self.assertIsInstance(template_attribute, expected, message)
attributes = template_attribute.attributes
expected = num_attributes
observed = len(attributes)
message = utils.build_er_error(TemplateAttribute.__class__, 'number',
expected, observed, 'attributes')
for i in xrange(num_attributes):
features = attribute_features[i]
self._check_attribute(attributes[i], features[0], features[1],
features[2], features[3])
def _check_attribute(self, attribute, attribute_name_type,
attribute_name_value, attribute_value_type,
attribute_value_value):
# Error check the attribute name and value type and value
attribute_name = attribute.attribute_name
attribute_value = attribute.attribute_value
self._check_attribute_name(attribute_name, attribute_name_type,
attribute_name_value)
if attribute_name_value == 'Unique Identifier':
self._check_uuid(attribute_value.value, attribute_value_type)
else:
self._check_attribute_value(attribute_value, attribute_value_type,
attribute_value_value)
def _check_attribute_name(self, attribute_name, attribute_name_type,
attribute_name_value):
# Error check the attribute name type and value
expected = attribute_name_type
observed = type(attribute_name.value)
message = utils.build_er_error(attribute_name_type, 'type', expected,
observed)
self.assertEqual(expected, observed, message)
expected = attribute_name_value
observed = attribute_name.value
message = utils.build_er_error(attribute_name_type, 'value', expected,
observed)
self.assertEqual(expected, observed, message)
def _check_attribute_value(self, attribute_value, attribute_value_type,
attribute_value_value):
expected = attribute_value_type
observed = type(attribute_value.value)
message = utils.build_er_error(Attribute, 'type', expected, observed,
'attribute_value')
self.assertEqual(expected, observed, message)
expected = attribute_value_value
observed = attribute_value.value
message = utils.build_er_error(Attribute, 'value', expected, observed,
'attribute_value')
self.assertEqual(expected, observed, message)

View File

@ -1,95 +0,0 @@
#!/usr/bin/env python
#
# Autogenerated by Thrift Compiler (0.9.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
# options string: py
#
import sys
import pprint
from urlparse import urlparse
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.transport import THttpClient
from thrift.protocol import TBinaryProtocol
from kmip import KMIP
from kmip.ttypes import *
if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print ''
print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]'
print ''
print 'Functions:'
print ' void create()'
print ' void register_mo()'
print ''
sys.exit(0)
pp = pprint.PrettyPrinter(indent = 2)
host = 'localhost'
port = 9090
uri = ''
framed = False
http = False
argi = 1
if sys.argv[argi] == '-h':
parts = sys.argv[argi+1].split(':')
host = parts[0]
if len(parts) > 1:
port = int(parts[1])
argi += 2
if sys.argv[argi] == '-u':
url = urlparse(sys.argv[argi+1])
parts = url[1].split(':')
host = parts[0]
if len(parts) > 1:
port = int(parts[1])
else:
port = 80
uri = url[2]
if url[4]:
uri += '?%s' % url[4]
http = True
argi += 2
if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':
framed = True
argi += 1
cmd = sys.argv[argi]
args = sys.argv[argi+1:]
if http:
transport = THttpClient.THttpClient(host, port, uri)
else:
socket = TSocket.TSocket(host, port)
if framed:
transport = TTransport.TFramedTransport(socket)
else:
transport = TTransport.TBufferedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = KMIP.Client(protocol)
transport.open()
if cmd == 'create':
if len(args) != 0:
print 'create requires 0 args'
sys.exit(1)
pp.pprint(client.create())
elif cmd == 'register_mo':
if len(args) != 0:
print 'register_mo requires 0 args'
sys.exit(1)
pp.pprint(client.register_mo())
else:
print 'Unrecognized method %s' % cmd
sys.exit(1)
transport.close()

View File

@ -1,295 +0,0 @@
#
# Autogenerated by Thrift Compiler (0.9.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
# options string: py
#
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
from ttypes import *
from thrift.Thrift import TProcessor
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol, TProtocol
try:
from thrift.protocol import fastbinary
except:
fastbinary = None
class Iface:
def create(self):
pass
def register_mo(self):
pass
class Client(Iface):
def __init__(self, iprot, oprot=None):
self._iprot = self._oprot = iprot
if oprot is not None:
self._oprot = oprot
self._seqid = 0
def create(self):
self.send_create()
self.recv_create()
def send_create(self):
self._oprot.writeMessageBegin('create', TMessageType.CALL, self._seqid)
args = create_args()
args.write(self._oprot)
self._oprot.writeMessageEnd()
self._oprot.trans.flush()
def recv_create(self):
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
if mtype == TMessageType.EXCEPTION:
x = TApplicationException()
x.read(self._iprot)
self._iprot.readMessageEnd()
raise x
result = create_result()
result.read(self._iprot)
self._iprot.readMessageEnd()
return
def register_mo(self):
self.send_register_mo()
self.recv_register_mo()
def send_register_mo(self):
self._oprot.writeMessageBegin('register_mo', TMessageType.CALL, self._seqid)
args = register_mo_args()
args.write(self._oprot)
self._oprot.writeMessageEnd()
self._oprot.trans.flush()
def recv_register_mo(self):
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
if mtype == TMessageType.EXCEPTION:
x = TApplicationException()
x.read(self._iprot)
self._iprot.readMessageEnd()
raise x
result = register_mo_result()
result.read(self._iprot)
self._iprot.readMessageEnd()
return
class Processor(Iface, TProcessor):
def __init__(self, handler):
self._handler = handler
self._processMap = {}
self._processMap["create"] = Processor.process_create
self._processMap["register_mo"] = Processor.process_register_mo
def process(self, iprot, oprot):
(name, type, seqid) = iprot.readMessageBegin()
if name not in self._processMap:
iprot.skip(TType.STRUCT)
iprot.readMessageEnd()
x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)
x.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
return
else:
self._processMap[name](self, seqid, iprot, oprot)
return True
def process_create(self, seqid, iprot, oprot):
args = create_args()
args.read(iprot)
iprot.readMessageEnd()
result = create_result()
self._handler.create()
oprot.writeMessageBegin("create", TMessageType.REPLY, seqid)
result.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
def process_register_mo(self, seqid, iprot, oprot):
args = register_mo_args()
args.read(iprot)
iprot.readMessageEnd()
result = register_mo_result()
self._handler.register_mo()
oprot.writeMessageBegin("register_mo", TMessageType.REPLY, seqid)
result.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
# HELPER FUNCTIONS AND STRUCTURES
class create_args:
thrift_spec = (
)
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('create_args')
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.iteritems()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class create_result:
thrift_spec = (
)
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('create_result')
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.iteritems()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class register_mo_args:
thrift_spec = (
)
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('register_mo_args')
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.iteritems()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class register_mo_result:
thrift_spec = (
)
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('register_mo_result')
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.iteritems()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)

View File

@ -1 +0,0 @@
__all__ = ['ttypes', 'constants', 'KMIP']

View File

@ -1,11 +0,0 @@
#
# Autogenerated by Thrift Compiler (0.9.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
# options string: py
#
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
from ttypes import *

View File

@ -1,18 +0,0 @@
#
# Autogenerated by Thrift Compiler (0.9.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
# options string: py
#
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol, TProtocol
try:
from thrift.protocol import fastbinary
except:
fastbinary = None

View File

@ -1 +1,4 @@
# TODO: Add any library dependencies here
enum34
sqlalchemy
thrift

42
setup.py Normal file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env python
#
# 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
#
# http://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.
import setuptools
setuptools.setup(
name='PyKMIP',
version='0.0.1',
description='KMIP v1.1 library',
keywords='KMIP',
author='Peter Hamilton',
author_email='peter.hamilton@jhuapl.edu',
url='http://www.jhuapl.edu',
license='Apache License, Version 2.0',
packages=setuptools.find_packages(exclude=["kmip.tests", "kmip.tests.*"]),
classifiers=[
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX",
"Operating System :: POSIX :: BSD",
"Operating System :: POSIX :: Linux",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
],
)

View File

@ -1 +1,11 @@
# TODO: add any test requirements here
coverage
pytest
flake8
testtools
fixtures
testresources
mock
testscenarios
testrepository
sphinx

View File

@ -1,43 +0,0 @@
/**
* This is the thrift definition file. It defines all of the methods and objects
* for the KMIP server. This file is used by thrift to generate the plumbing for
* a KMIP client and server.
*
* This file generated the files under kmip/thrift.
*
* If this file is updated then run the following command to update the
* kmip/thrift directory.
*
* thrift -o kmip -r --gen py thrift/tutorial.thrift
*/
/**
* The first thing to know about are types. The available types in Thrift are:
*
* bool Boolean, one byte
* byte Signed byte
* i16 Signed 16-bit integer
* i32 Signed 32-bit integer
* i64 Signed 64-bit integer
* double 64-bit floating point value
* string String
* binary Blob (byte array)
* map<t1,t2> Map from one type to another
* list<t1> Ordered list of one type
* set<t1> Set of unique elements of one type
*
*/
namespace cpp thrift
namespace d thrift
namespace java thrift
namespace php thrift
namespace perl thrift
service KMIP {
void create(),
/* Did not use register because it is a reserved word */
void register_mo()
}

16
tox.ini Normal file
View File

@ -0,0 +1,16 @@
[tox]
envlist = pep8,py27,py26
[testenv]
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands =
coverage run --source=kmip/ -m pytest --strict {posargs}
coverage report
[testenv:pep8]
commands = flake8 {posargs}
[flake8]
exclude = .git,.tox,dist,rpmbuild,*.egg-info