├── .github └── workflows │ └── test.yml ├── .gitignore ├── .golangci.yml ├── LICENSE ├── Makefile ├── README.md ├── attribute.go ├── auth.go ├── client.go ├── consts.go ├── decode.go ├── decode_core.go ├── decode_test.go ├── doc.go ├── encode.go ├── encode_core.go ├── encode_test.go ├── errors.go ├── fields.go ├── go.mod ├── go.sum ├── keys.go ├── operations.go ├── request.go ├── request_test.go ├── response.go ├── server.go ├── server_test.go ├── tls.go ├── tls_test.go └── types.go /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Test 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | go-version: [1.15.x, 1.16.x] 8 | os: [ubuntu-latest, macos-latest] 9 | runs-on: ${{ matrix.os }} 10 | steps: 11 | - name: Install Go 12 | uses: actions/setup-go@v2 13 | with: 14 | go-version: ${{ matrix.go-version }} 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | - uses: actions/cache@v2 18 | with: 19 | # In order: 20 | # * Module download cache 21 | # * Build cache (Linux) 22 | # * Build cache (Mac) 23 | # * Build cache (Windows) 24 | path: | 25 | ~/go/pkg/mod 26 | ~/.cache/go-build 27 | ~/Library/Caches/go-build 28 | %LocalAppData%\go-build 29 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 30 | restore-keys: | 31 | ${{ runner.os }}-go- 32 | - name: Test 33 | run: go test ./... 34 | - name: golangci-lint 35 | uses: golangci/golangci-lint-action@v2 36 | with: 37 | # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version 38 | version: latest 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | coverage.txt 27 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | enable: 3 | - gofmt 4 | - gosec 5 | - unconvert 6 | - goimports 7 | - misspell 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: test lint 2 | 3 | .PHONY: test 4 | test: 5 | go test -v -race -coverprofile=coverage.txt -covermode=atomic -count 1 . 6 | 7 | .PHONY: lint 8 | lint: 9 | golangci-lint run 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | go-kmip 2 | ======= 3 | 4 | [![Build Status](https://travis-ci.org/smira/go-kmip.svg?branch=master)](https://travis-ci.org/smira/go-kmip) 5 | [![codecov](https://codecov.io/gh/smira/go-kmip/branch/master/graph/badge.svg)](https://codecov.io/gh/smira/go-kmip) 6 | [![Documentation](https://godoc.org/github.com/smira/go-kmip?status.svg)](http://godoc.org/github.com/smira/go-kmip) 7 | [![Go Report Card](https://goreportcard.com/badge/github.com/smira/go-kmip)](https://goreportcard.com/report/github.com/smira/go-kmip) 8 | 9 | go-kmip implements subset of [KMIP 1.4](http://docs.oasis-open.org/kmip/spec/v1.4/os/kmip-spec-v1.4-os.html) protocol. 10 | 11 | Basic TTLV encoding/decoding is fully implemented, as well as the basic client/server operations. 12 | Other operations and fields could be implemented by adding required Go structures with KMIP tags. 13 | 14 | KMIP protocol is used to access KMS solutions: generating keys, certificates, 15 | accessing stored objects, etc. 16 | 17 | KMIP is using TTLV-like encoding, which is implemented in this packaged 18 | as encoding/decoding of Go struct types. Go struct fields are annotated with 19 | `kmip` tags which specify KMIP tag names. Field is encoded/decoded according 20 | to its tag, type. 21 | 22 | Two high-level objects are implemented: Server and Client. Server listens for 23 | TLS connections, does initial handshake and processes batch requests from the 24 | clients. Processing of specific operations is delegated to operation handlers. 25 | Client objects establishes connection with the KMIP server and allows sending 26 | any number of requests over the connection. 27 | 28 | This package doesn't implement any actual key processing or management - it's outside 29 | the scope of this package. 30 | 31 | License 32 | ------- 33 | 34 | This code is licensed under [MPL 2.0](https://www.mozilla.org/en-US/MPL/2.0/). 35 | -------------------------------------------------------------------------------- /attribute.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "time" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | // Attribute is a Attribute Object Structure 14 | type Attribute struct { 15 | Tag `kmip:"ATTRIBUTE"` 16 | 17 | Name string `kmip:"ATTRIBUTE_NAME"` 18 | Index int32 `kmip:"ATTRIBUTE_INDEX"` 19 | Value interface{} `kmip:"ATTRIBUTE_VALUE"` 20 | } 21 | 22 | // BuildFieldValue builds dynamic Value field 23 | func (a *Attribute) BuildFieldValue(name string) (v interface{}, err error) { 24 | switch a.Name { 25 | case ATTRIBUTE_NAME_CRYPTOGRAPHIC_ALGORITHM: 26 | v = Enum(0) 27 | case ATTRIBUTE_NAME_CRYPTOGRAPHIC_LENGTH, ATTRIBUTE_NAME_CRYPTOGRAPHIC_USAGE_MASK: 28 | v = int32(0) 29 | case ATTRIBUTE_NAME_UNIQUE_IDENTIFIER, ATTRIBUTE_NAME_OPERATION_POLICY_NAME: 30 | v = "" 31 | case ATTRIBUTE_NAME_OBJECT_TYPE, ATTRIBUTE_NAME_STATE: 32 | v = Enum(0) 33 | case ATTRIBUTE_NAME_INITIAL_DATE, ATTRIBUTE_NAME_LAST_CHANGE_DATE: 34 | v = time.Time{} 35 | case ATTRIBUTE_NAME_NAME: 36 | v = &Name{} 37 | case ATTRIBUTE_NAME_DIGEST: 38 | v = &Digest{} 39 | default: 40 | err = errors.Errorf("unsupported attribute: %v", a.Name) 41 | } 42 | 43 | return 44 | } 45 | 46 | // Attributes is a sequence of Attribute objects which allows building and search 47 | type Attributes []Attribute 48 | 49 | func (attrs Attributes) Get(name string) (val interface{}) { 50 | for i := range attrs { 51 | if attrs[i].Name == name { 52 | val = attrs[i].Value 53 | break 54 | } 55 | } 56 | 57 | return 58 | } 59 | 60 | // TemplateAttribute is a Template-Attribute Object Structure 61 | type TemplateAttribute struct { 62 | Tag `kmip:"TEMPLATE_ATTRIBUTE"` 63 | 64 | Name Name `kmip:"NAME"` 65 | Attributes Attributes `kmip:"ATTRIBUTE"` 66 | } 67 | 68 | // Name is a Name Attribute Structure 69 | type Name struct { 70 | Tag `kmip:"NAME"` 71 | 72 | Value string `kmip:"NAME_VALUE,required"` 73 | Type Enum `kmip:"NAME_TYPE,required"` 74 | } 75 | 76 | // Digest is a Digest Attribute Structure 77 | type Digest struct { 78 | Tag `kmip:"DIGEST"` 79 | 80 | HashingAlgorithm Enum `kmip:"HASHING_ALGORITHM,required"` 81 | DigestValue []byte `kmip:"DIGEST_VALUE"` 82 | KeyFormatType Enum `kmip:"KEY_FORMAT_TYPE"` 83 | } 84 | -------------------------------------------------------------------------------- /auth.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import "github.com/pkg/errors" 8 | 9 | // Authentication is an Authentication structure 10 | type Authentication struct { 11 | Tag `kmip:"AUTHENTICATION"` 12 | 13 | CredentialType Enum `kmip:"CREDENTIAL_TYPE,required"` 14 | CredentialValue interface{} `kmip:"CREDENTIAL_VALUE,required"` 15 | } 16 | 17 | // BuildFieldValue builds value for CredentialValue based on CredentialType 18 | func (a *Authentication) BuildFieldValue(name string) (v interface{}, err error) { 19 | switch a.CredentialType { 20 | case CREDENTIAL_TYPE_USERNAME_AND_PASSWORD: 21 | v = &CredentialUsernamePassword{} 22 | default: 23 | err = errors.Errorf("unsupported credential type: %v", a.CredentialType) 24 | } 25 | 26 | return 27 | } 28 | 29 | // CredentialUsernamePassword is a Credential structure for username/password authentication 30 | type CredentialUsernamePassword struct { 31 | Tag `kmip:"CREDENTIAL_VALUE"` 32 | 33 | Username string `kmip:"USERNAME,required"` 34 | Password string `kmip:"PASSWORD,required"` 35 | } 36 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "crypto/tls" 9 | "time" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | // Client implements basic KMIP client 15 | // 16 | // Client is not safe for concurrent use 17 | type Client struct { 18 | // Server endpoint as "host:port" 19 | Endpoint string 20 | 21 | // TLS client config 22 | TLSConfig *tls.Config 23 | 24 | // KMIP version to use 25 | // 26 | // Defaults to DefaultSupportedVersions[0] if not set 27 | Version ProtocolVersion 28 | 29 | // Network timeouts 30 | ReadTimeout, WriteTimeout time.Duration 31 | 32 | conn *tls.Conn 33 | e *Encoder 34 | d *Decoder 35 | } 36 | 37 | // Connect establishes connection with the server 38 | func (c *Client) Connect() error { 39 | var err error 40 | 41 | if c.conn, err = tls.Dial("tcp", c.Endpoint, c.TLSConfig); err != nil { 42 | return errors.Wrap(err, "error dialing connection") 43 | } 44 | 45 | if c.ReadTimeout != 0 { 46 | _ = c.conn.SetReadDeadline(time.Now().Add(c.ReadTimeout)) 47 | } 48 | 49 | if c.WriteTimeout != 0 { 50 | _ = c.conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout)) 51 | } 52 | 53 | if err = c.conn.Handshake(); err != nil { 54 | return errors.Wrap(err, "error running tls handshake") 55 | } 56 | 57 | var zeroVersion ProtocolVersion 58 | if c.Version == zeroVersion { 59 | c.Version = DefaultSupportedVersions[0] 60 | } 61 | 62 | c.e = NewEncoder(c.conn) 63 | c.d = NewDecoder(c.conn) 64 | 65 | return nil 66 | } 67 | 68 | // Close connection to the server 69 | func (c *Client) Close() error { 70 | if c.conn == nil { 71 | return nil 72 | } 73 | 74 | err := c.conn.Close() 75 | c.conn = nil 76 | 77 | return err 78 | } 79 | 80 | // DiscoverVersions with the server 81 | func (c *Client) DiscoverVersions(versions []ProtocolVersion) (serverVersions []ProtocolVersion, err error) { 82 | var resp interface{} 83 | resp, err = c.Send(OPERATION_DISCOVER_VERSIONS, 84 | DiscoverVersionsRequest{ 85 | ProtocolVersions: versions, 86 | }) 87 | 88 | if err != nil { 89 | return 90 | } 91 | 92 | serverVersions = resp.(DiscoverVersionsResponse).ProtocolVersions 93 | return 94 | } 95 | 96 | // Send request to server and deliver response/error back 97 | // 98 | // Request payload should be passed as req, and response payload will be 99 | // returned back as resp. Operation will be sent as a batch with single 100 | // item. 101 | // 102 | // Send is a generic method, it's better to implement specific methods for 103 | // each operation (use DiscoverVersions as example). 104 | func (c *Client) Send(operation Enum, req interface{}) (resp interface{}, err error) { 105 | if c.conn == nil { 106 | err = errors.New("not connected") 107 | return 108 | } 109 | 110 | request := &Request{ 111 | Header: RequestHeader{ 112 | Version: c.Version, 113 | BatchCount: 1, 114 | }, 115 | BatchItems: []RequestBatchItem{ 116 | { 117 | Operation: operation, 118 | RequestPayload: req, 119 | }, 120 | }, 121 | } 122 | 123 | if c.WriteTimeout != 0 { 124 | _ = c.conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout)) 125 | } 126 | 127 | err = c.e.Encode(request) 128 | if err != nil { 129 | err = errors.Wrap(err, "error writing request") 130 | return 131 | } 132 | 133 | if c.ReadTimeout != 0 { 134 | _ = c.conn.SetReadDeadline(time.Now().Add(c.ReadTimeout)) 135 | } 136 | 137 | var response Response 138 | 139 | err = c.d.Decode(&response) 140 | if err != nil { 141 | err = errors.Wrap(err, "error reading response") 142 | return 143 | } 144 | 145 | if response.Header.BatchCount != 1 { 146 | err = errors.Errorf("unexepcted response batch count: %d", response.Header.BatchCount) 147 | return 148 | } 149 | 150 | if len(response.BatchItems) != 1 { 151 | err = errors.Errorf("unexpected response batch items: %d", len(response.BatchItems)) 152 | return 153 | } 154 | 155 | if response.BatchItems[0].Operation != operation { 156 | err = errors.Errorf("unexpected response operation: %d", response.BatchItems[0].Operation) 157 | return 158 | } 159 | 160 | if response.BatchItems[0].ResultStatus == RESULT_STATUS_SUCCESS { 161 | resp = response.BatchItems[0].ResponsePayload 162 | return 163 | } 164 | 165 | err = wrapError(errors.New(response.BatchItems[0].ResultMessage), response.BatchItems[0].ResultReason) 166 | return 167 | } 168 | -------------------------------------------------------------------------------- /consts.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | // KMIP Tags 8 | const ( 9 | // Internal 10 | ANY_TAG Tag = 0xffffff 11 | // KMIP 1.0 12 | ACTIVATION_DATE Tag = 0x420001 13 | APPLICATION_DATA Tag = 0x420002 14 | APPLICATION_NAMESPACE Tag = 0x420003 15 | APPLICATION_SPECIFIC_INFORMATION Tag = 0x420004 16 | ARCHIVE_DATE Tag = 0x420005 17 | ASYNCHRONOUS_CORRELATION_VALUE Tag = 0x420006 18 | ASYNCHRONOUS_INDICATOR Tag = 0x420007 19 | ATTRIBUTE Tag = 0x420008 20 | ATTRIBUTE_INDEX Tag = 0x420009 // Designated '(Reserved)' in KMIP 2.0 21 | ATTRIBUTE_NAME Tag = 0x42000A 22 | ATTRIBUTE_VALUE Tag = 0x42000B 23 | AUTHENTICATION Tag = 0x42000C 24 | BATCH_COUNT Tag = 0x42000D 25 | BATCH_ERROR_CONTINUATION_OPTION Tag = 0x42000E 26 | BATCH_ITEM Tag = 0x42000F 27 | BATCH_ORDER_OPTION Tag = 0x420010 28 | BLOCK_CIPHER_MODE Tag = 0x420011 29 | CANCELLATION_RESULT Tag = 0x420012 30 | CERTIFICATE Tag = 0x420013 31 | CERTIFICATE_IDENTIFIER Tag = 0x420014 // Deprecated, designated '(Reserved)' in KMIP 2.0 32 | CERTIFICATE_ISSUER Tag = 0x420015 // Deprecated, designated '(Reserved)' in KMIP 2.0 33 | CERTIFICATE_ISSUER_ALTERNATIVE_NAME Tag = 0x420016 // Deprecated, designated '(Reserved)' in KMIP 2.0 34 | CERTIFICATE_ISSUER_DISTINGUISHED_NAME Tag = 0x420017 // Deprecated, designated '(Reserved)' in KMIP 2.0 35 | CERTIFICATE_REQUEST Tag = 0x420018 36 | CERTIFICATE_REQUEST_TYPE Tag = 0x420019 37 | CERTIFICATE_SUBJECT Tag = 0x42001A // Deprecated, designated '(Reserved)' in KMIP 2.0 38 | CERTIFICATE_SUBJECT_ALTERNATIVE_NAME Tag = 0x42001B // Deprecated, designated '(Reserved)' in KMIP 2.0 39 | CERTIFICATE_SUBJECT_DISTINGUISHED_NAME Tag = 0x42001C // Deprecated, designated '(Reserved)' in KMIP 2.0 40 | CERTIFICATE_TYPE Tag = 0x42001D 41 | CERTIFICATE_VALUE Tag = 0x42001E 42 | COMMON_TEMPLATE_ATTRIBUTE Tag = 0x42001F // Designated '(Reserved)' in KMIP 2.0 43 | COMPROMISE_DATE Tag = 0x420020 44 | COMPROMISE_OCCURRENCE_DATE Tag = 0x420021 45 | CONTACT_INFORMATION Tag = 0x420022 46 | CREDENTIAL Tag = 0x420023 47 | CREDENTIAL_TYPE Tag = 0x420024 48 | CREDENTIAL_VALUE Tag = 0x420025 49 | CRITICALITY_INDICATOR Tag = 0x420026 50 | CRT_COEFFICIENT Tag = 0x420027 51 | CRYPTOGRAPHIC_ALGORITHM Tag = 0x420028 52 | CRYPTOGRAPHIC_DOMAIN_PARAMETERS Tag = 0x420029 53 | CRYPTOGRAPHIC_LENGTH Tag = 0x42002A 54 | CRYPTOGRAPHIC_PARAMETERS Tag = 0x42002B 55 | CRYPTOGRAPHIC_USAGE_MASK Tag = 0x42002C 56 | CUSTOM_ATTRIBUTE Tag = 0x42002D // Designated '(Reserved)' in KMIP 2.0 57 | D Tag = 0x42002E 58 | DEACTIVATION_DATE Tag = 0x42002F 59 | DERIVATION_DATA Tag = 0x420030 60 | DERIVATION_METHOD Tag = 0x420031 61 | DERIVATION_PARAMETERS Tag = 0x420032 62 | DESTROY_DATE Tag = 0x420033 63 | DIGEST Tag = 0x420034 64 | DIGEST_VALUE Tag = 0x420035 65 | ENCRYPTION_KEY_INFORMATION Tag = 0x420036 66 | G Tag = 0x420037 67 | HASHING_ALGORITHM Tag = 0x420038 68 | INITIAL_DATE Tag = 0x420039 69 | INITIALIZATION_VECTOR Tag = 0x42003A 70 | ISSUER Tag = 0x42003B // Deprecated, designated '(Reserved)' in KMIP 2.0 71 | ITERATION_COUNT Tag = 0x42003C 72 | IV_COUNTER_NONCE Tag = 0x42003D 73 | J Tag = 0x42003E 74 | KEY Tag = 0x42003F 75 | KEY_BLOCK Tag = 0x420040 76 | KEY_COMPRESSION_TYPE Tag = 0x420041 77 | KEY_FORMAT_TYPE Tag = 0x420042 78 | KEY_MATERIAL Tag = 0x420043 79 | KEY_PART_IDENTIFIER Tag = 0x420044 80 | KEY_VALUE Tag = 0x420045 81 | KEY_WRAPPING_DATA Tag = 0x420046 82 | KEY_WRAPPING_SPECIFICATION Tag = 0x420047 83 | LAST_CHANGE_DATE Tag = 0x420048 84 | LEASE_TIME Tag = 0x420049 85 | LINK Tag = 0x42004A 86 | LINK_TYPE Tag = 0x42004B 87 | LINKED_OBJECT_IDENTIFIER Tag = 0x42004C 88 | MAC_SIGNATURE Tag = 0x42004D 89 | MAC_SIGNATURE_KEY_INFORMATION Tag = 0x42004E 90 | MAXIMUM_ITEMS Tag = 0x42004F 91 | MAXIMUM_RESPONSE_SIZE Tag = 0x420050 92 | MESSAGE_EXTENSION Tag = 0x420051 93 | MODULUS Tag = 0x420052 94 | NAME Tag = 0x420053 95 | NAME_TYPE Tag = 0x420054 96 | NAME_VALUE Tag = 0x420055 97 | OBJECT_GROUP Tag = 0x420056 98 | OBJECT_TYPE Tag = 0x420057 99 | OFFSET Tag = 0x420058 100 | OPAQUE_DATA_TYPE Tag = 0x420059 101 | OPAQUE_DATA_VALUE Tag = 0x42005A 102 | OPAQUE_OBJECT Tag = 0x42005B 103 | OPERATION Tag = 0x42005C 104 | OPERATION_POLICY_NAME Tag = 0x42005D // Designated '(Reserved)' in KMIP 2.0 105 | P Tag = 0x42005E 106 | PADDING_METHOD Tag = 0x42005F 107 | PRIME_EXPONENT_P Tag = 0x420060 108 | PRIME_EXPONENT_Q Tag = 0x420061 109 | PRIME_FIELD_SIZE Tag = 0x420062 110 | PRIVATE_EXPONENT Tag = 0x420063 111 | PRIVATE_KEY Tag = 0x420064 112 | PRIVATE_KEY_TEMPLATE_ATTRIBUTE Tag = 0x420065 // Designated '(Reserved)' in KMIP 2.0 113 | PRIVATE_KEY_UNIQUE_IDENTIFIER Tag = 0x420066 114 | PROCESS_START_DATE Tag = 0x420067 115 | PROTECT_STOP_DATE Tag = 0x420068 116 | PROTOCOL_VERSION Tag = 0x420069 117 | PROTOCOL_VERSION_MAJOR Tag = 0x42006A 118 | PROTOCOL_VERSION_MINOR Tag = 0x42006B 119 | PUBLIC_EXPONENT Tag = 0x42006C 120 | PUBLIC_KEY Tag = 0x42006D 121 | PUBLIC_KEY_TEMPLATE_ATTRIBUTE Tag = 0x42006E // Designated '(Reserved)' in KMIP 2.0 122 | PUBLIC_KEY_UNIQUE_IDENTIFIER Tag = 0x42006F 123 | PUT_FUNCTION Tag = 0x420070 124 | Q Tag = 0x420071 125 | Q_STRING Tag = 0x420072 126 | QLENGTH Tag = 0x420073 127 | QUERY_FUNCTION Tag = 0x420074 128 | RECOMMENDED_CURVE Tag = 0x420075 129 | REPLACED_UNIQUE_IDENTIFIER Tag = 0x420076 130 | REQUEST_BATCH_ITEM Tag = 0x42000F 131 | REQUEST_HEADER Tag = 0x420077 132 | REQUEST_MESSAGE Tag = 0x420078 133 | REQUEST_PAYLOAD Tag = 0x420079 134 | RESPONSE_BATCH_ITEM Tag = 0x42000F 135 | RESPONSE_HEADER Tag = 0x42007A 136 | RESPONSE_MESSAGE Tag = 0x42007B 137 | RESPONSE_PAYLOAD Tag = 0x42007C 138 | RESULT_MESSAGE Tag = 0x42007D 139 | RESULT_REASON Tag = 0x42007E 140 | RESULT_STATUS Tag = 0x42007F 141 | REVOCATION_MESSAGE Tag = 0x420080 142 | REVOCATION_REASON Tag = 0x420081 143 | REVOCATION_REASON_CODE Tag = 0x420082 144 | KEY_ROLE_TYPE Tag = 0x420083 145 | SALT Tag = 0x420084 146 | SECRET_DATA Tag = 0x420085 147 | SECRET_DATA_TYPE Tag = 0x420086 148 | SERIAL_NUMBER Tag = 0x420087 // Deprecated, designated '(Reserved)' in KMIP 2.0 149 | SERVER_INFORMATION Tag = 0x420088 150 | SPLIT_KEY Tag = 0x420089 151 | SPLIT_KEY_METHOD Tag = 0x42008A 152 | SPLIT_KEY_PARTS Tag = 0x42008B 153 | SPLIT_KEY_THRESHOLD Tag = 0x42008C 154 | STATE Tag = 0x42008D 155 | STORAGE_STATUS_MASK Tag = 0x42008E 156 | SYMMETRIC_KEY Tag = 0x42008F 157 | TEMPLATE Tag = 0x420090 // Designated '(Reserved)' in KMIP 2.0 158 | TEMPLATE_ATTRIBUTE Tag = 0x420091 // Designated '(Reserved)' in KMIP 2.0 159 | TIME_STAMP Tag = 0x420092 160 | UNIQUE_BATCH_ITEM_ID Tag = 0x420093 161 | UNIQUE_IDENTIFIER Tag = 0x420094 162 | USAGE_LIMITS Tag = 0x420095 163 | USAGE_LIMITS_COUNT Tag = 0x420096 164 | USAGE_LIMITS_TOTAL Tag = 0x420097 165 | USAGE_LIMITS_UNIT Tag = 0x420098 166 | USERNAME Tag = 0x420099 167 | VALIDITY_DATE Tag = 0x42009A 168 | VALIDITY_INDICATOR Tag = 0x42009B 169 | VENDOR_EXTENSION Tag = 0x42009C 170 | VENDOR_IDENTIFICATION Tag = 0x42009D 171 | WRAPPING_METHOD Tag = 0x42009E 172 | X Tag = 0x42009F 173 | Y Tag = 0x4200A0 174 | PASSWORD Tag = 0x4200A1 175 | // KMIP 1.1 176 | DEVICE_IDENTIFIER Tag = 0x4200A2 177 | ENCODING_OPTION Tag = 0x4200A3 178 | EXTENSION_INFORMATION Tag = 0x4200A4 179 | EXTENSION_NAME Tag = 0x4200A5 180 | EXTENSION_TAG Tag = 0x4200A6 181 | EXTENSION_TYPE Tag = 0x4200A7 182 | FRESH Tag = 0x4200A8 183 | MACHINE_IDENTIFIER Tag = 0x4200A9 184 | MEDIA_IDENTIFIER Tag = 0x4200AA 185 | NETWORK_IDENTIFIER Tag = 0x4200AB 186 | OBJECT_GROUP_MEMBER Tag = 0x4200AC 187 | CERTIFICATE_LENGTH Tag = 0x4200AD 188 | DIGITAL_SIGNATURE_ALGORITHM Tag = 0x4200AE 189 | CERTIFICATE_SERIAL_NUMBER Tag = 0x4200AF 190 | DEVICE_SERIAL_NUMBER Tag = 0x4200B0 191 | ISSUER_ALTERNATIVE_NAME Tag = 0x4200B1 192 | ISSUER_DISTINGUISHED_NAME Tag = 0x4200B2 193 | SUBJECT_ALTERNATIVE_NAME Tag = 0x4200B3 194 | SUBJECT_DISTINGUISHED_NAME Tag = 0x4200B4 195 | X_509_CERTIFICATE_IDENTIFIER Tag = 0x4200B5 196 | X_509_CERTIFICATE_ISSUER Tag = 0x4200B6 197 | X_509_CERTIFICATE_SUBJECT Tag = 0x4200B7 198 | // KMIP 1.2 199 | KEY_VALUE_LOCATION Tag = 0x4200B8 200 | KEY_VALUE_LOCATION_VALUE Tag = 0x4200B9 201 | KEY_VALUE_LOCATION_TYPE Tag = 0x4200BA 202 | KEY_VALUE_PRESENT Tag = 0x4200BB 203 | ORIGINAL_CREATION_DATE Tag = 0x4200BC 204 | PGP_KEY Tag = 0x4200BD 205 | PGP_KEY_VERSION Tag = 0x4200BE 206 | ALTERNATIVE_NAME Tag = 0x4200BF 207 | ALTERNATIVE_NAME_VALUE Tag = 0x4200C0 208 | ALTERNATIVE_NAME_TYPE Tag = 0x4200C1 209 | DATA Tag = 0x4200C2 210 | SIGNATURE_DATA Tag = 0x4200C3 211 | DATA_LENGTH Tag = 0x4200C4 212 | RANDOM_IV Tag = 0x4200C5 213 | MAC_DATA Tag = 0x4200C6 214 | ATTESTATION_TYPE Tag = 0x4200C7 215 | NONCE Tag = 0x4200C8 216 | NONCE_ID Tag = 0x4200C9 217 | NONCE_VALUE Tag = 0x4200CA 218 | ATTESTATION_MEASUREMENT Tag = 0x4200CB 219 | ATTESTATION_ASSERTION Tag = 0x4200CC 220 | IV_LENGTH Tag = 0x4200CD 221 | TAG_LENGTH Tag = 0x4200CE 222 | FIXED_FIELD_LENGTH Tag = 0x4200CF 223 | COUNTER_LENGTH Tag = 0x4200D0 224 | INITIAL_COUNTER_VALUE Tag = 0x4200D1 225 | INVOCATION_FIELD_LENGTH Tag = 0x4200D2 226 | ATTESTATION_CAPABLE_INDICATOR Tag = 0x4200D3 227 | // KMIP 1.3 228 | OFFSET_ITEMS Tag = 0x4200D4 229 | LOCATED_ITEMS Tag = 0x4200D5 230 | CORRELATION_VALUE Tag = 0x4200D6 231 | INIT_INDICATOR Tag = 0x4200D7 232 | FINAL_INDICATOR Tag = 0x4200D8 233 | RNG_PARAMETERS Tag = 0x4200D9 234 | RNG_ALGORITHM Tag = 0x4200DA 235 | DRBG_ALGORITHM Tag = 0x4200DB 236 | FIPS186_VARIATION Tag = 0x4200DC 237 | PREDICTION_RESISTANCE Tag = 0x4200DD 238 | RANDOM_NUMBER_GENERATOR Tag = 0x4200DE 239 | VALIDATION_INFORMATION Tag = 0x4200DF 240 | VALIDATION_AUTHORITY_TYPE Tag = 0x4200E0 241 | VALIDATION_AUTHORITY_COUNTRY Tag = 0x4200E1 242 | VALIDATION_AUTHORITY_URI Tag = 0x4200E2 243 | VALIDATION_VERSION_MAJOR Tag = 0x4200E3 244 | VALIDATION_VERSION_MINOR Tag = 0x4200E4 245 | VALIDATION_TYPE Tag = 0x4200E5 246 | VALIDATION_LEVEL Tag = 0x4200E6 247 | VALIDATION_CERTIFICATE_IDENTIFIER Tag = 0x4200E7 248 | VALIDATION_CERTIFICATE_URI Tag = 0x4200E8 249 | VALIDATION_VENDOR_URI Tag = 0x4200E9 250 | VALIDATION_PROFILE Tag = 0x4200EA 251 | PROFILE_INFORMATION Tag = 0x4200EB 252 | PROFILE_NAME Tag = 0x4200EC 253 | SERVER_URI Tag = 0x4200ED 254 | SERVER_PORT Tag = 0x4200EE 255 | STREAMING_CAPABILITY Tag = 0x4200EF 256 | ASYNCHRONOUS_CAPABILITY Tag = 0x4200F0 257 | ATTESTATION_CAPABILITY Tag = 0x4200F1 258 | UNWRAP_MODE Tag = 0x4200F2 259 | DESTROY_ACTION Tag = 0x4200F3 260 | SHREDDING_ALGORITHM Tag = 0x4200F4 261 | RNG_MODE Tag = 0x4200F5 262 | CLIENT_REGISTRATION_METHOD Tag = 0x4200F6 263 | CAPABILITY_INFORMATION Tag = 0x4200F7 264 | // KMIP 1.4 265 | KEY_WRAP_TYPE Tag = 0x4200F8 266 | BATCH_UNDO_CAPABILITY Tag = 0x4200F9 267 | BATCH_CONTINUE_CAPABILITY Tag = 0x4200FA 268 | PKCS12_FRIENDLY_NAME Tag = 0x4200FB 269 | DESCRIPTION Tag = 0x4200FC 270 | COMMENT Tag = 0x4200FD 271 | AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA Tag = 0x4200FE 272 | AUTHENTICATED_ENCRYPTION_TAG Tag = 0x4200FF 273 | SALT_LENGTH Tag = 0x420100 274 | MASK_GENERATOR Tag = 0x420101 275 | MASK_GENERATOR_HASHING_ALGORITHM Tag = 0x420102 276 | P_SOURCE Tag = 0x420103 277 | TRAILER_FIELD Tag = 0x420104 278 | CLIENT_CORRELATION_VALUE Tag = 0x420105 279 | SERVER_CORRELATION_VALUE Tag = 0x420106 280 | DIGESTED_DATA Tag = 0x420107 281 | CERTIFICATE_SUBJECT_CN Tag = 0x420108 282 | CERTIFICATE_SUBJECT_O Tag = 0x420109 283 | CERTIFICATE_SUBJECT_OU Tag = 0x42010A 284 | CERTIFICATE_SUBJECT_EMAIL Tag = 0x42010B 285 | CERTIFICATE_SUBJECT_C Tag = 0x42010C 286 | CERTIFICATE_SUBJECT_ST Tag = 0x42010D 287 | CERTIFICATE_SUBJECT_L Tag = 0x42010E 288 | CERTIFICATE_SUBJECT_UID Tag = 0x42010F 289 | CERTIFICATE_SUBJECT_SERIAL_NUMBER Tag = 0x420110 290 | CERTIFICATE_SUBJECT_TITLE Tag = 0x420111 291 | CERTIFICATE_SUBJECT_DC Tag = 0x420112 292 | CERTIFICATE_SUBJECT_DN_QUALIFIER Tag = 0x420113 293 | CERTIFICATE_ISSUER_CN Tag = 0x420114 294 | CERTIFICATE_ISSUER_O Tag = 0x420115 295 | CERTIFICATE_ISSUER_OU Tag = 0x420116 296 | CERTIFICATE_ISSUER_EMAIL Tag = 0x420117 297 | CERTIFICATE_ISSUER_C Tag = 0x420118 298 | CERTIFICATE_ISSUER_ST Tag = 0x420119 299 | CERTIFICATE_ISSUER_L Tag = 0x42011A 300 | CERTIFICATE_ISSUER_UID Tag = 0x42011B 301 | CERTIFICATE_ISSUER_SERIAL_NUMBER Tag = 0x42011C 302 | CERTIFICATE_ISSUER_TITLE Tag = 0x42011D 303 | CERTIFICATE_ISSUER_DC Tag = 0x42011E 304 | CERTIFICATE_ISSUER_DN_QUALIFIER Tag = 0x42011F 305 | SENSITIVE Tag = 0x420120 306 | ALWAYS_SENSITIVE Tag = 0x420121 307 | EXTRACTABLE Tag = 0x420122 308 | NEVER_EXTRACTABLE Tag = 0x420123 309 | REPLACE_EXISTING Tag = 0x420124 310 | // KMIP 2.0 311 | ATTRIBUTES Tag = 0x420125 312 | COMMON_ATTRIBUTES Tag = 0x420126 313 | PRIVATE_KEY_ATTRIBUTES Tag = 0x420127 314 | PUBLIC_KEY_ATTRIBUTES Tag = 0x420128 315 | EXTENSION_ENUMERATION Tag = 0x420129 316 | EXTENSION_ATTRIBUTE Tag = 0x42012A 317 | EXTENSION_PARENT_STRUCTURE_TAG Tag = 0x42012B 318 | EXTENSION_DESCRIPTION Tag = 0x42012C 319 | SERVER_NAME Tag = 0x42012D 320 | SERVER_SERIAL_NUMBER Tag = 0x42012E 321 | SERVER_VERSION Tag = 0x42012F 322 | SERVER_LOAD Tag = 0x420130 323 | PRODUCT_NAME Tag = 0x420131 324 | BUILD_LEVEL Tag = 0x420132 325 | BUILD_DATE Tag = 0x420133 326 | CLUSTER_INFO Tag = 0x420134 327 | ALTERNATE_FAILOVER_ENDPOINTS Tag = 0x420135 328 | SHORT_UNIQUE_IDENTIFIER Tag = 0x420136 329 | RESERVED Tag = 0x420137 330 | TAG Tag = 0x420138 331 | CERTIFICATE_REQUEST_UNIQUE_IDENTIFIER Tag = 0x420139 332 | NIST_KEY_TYPE Tag = 0x42013A 333 | ATTRIBUTE_REFERENCE Tag = 0x42013B 334 | CURRENT_ATTRIBUTE Tag = 0x42013C 335 | NEW_ATTRIBUTE Tag = 0x42013D 336 | // 0x42013E is designated '(Reserved)' in KMIP 2.0 337 | // 0x42013F is designated '(Reserved)' in KMIP 2.0 338 | CERTIFICATE_REQUEST_VALUE Tag = 0x420140 339 | LOG_MESSAGE Tag = 0x420141 340 | PROFILE_VERSION Tag = 0x420142 341 | PROFILE_VERSION_MAJOR Tag = 0x420143 342 | PROFILE_VERSION_MINOR Tag = 0x420144 343 | PROTECTION_LEVEL Tag = 0x420145 344 | PROTECTION_PERIOD Tag = 0x420146 345 | QUANTUM_SAFE Tag = 0x420147 346 | QUANTUM_SAFE_CAPABILITY Tag = 0x420148 347 | TICKET Tag = 0x420149 348 | TICKET_TYPE Tag = 0x42014A 349 | TICKET_VALUE Tag = 0x42014B 350 | REQUEST_COUNT Tag = 0x42014C 351 | RIGHTS Tag = 0x42014D 352 | OBJECTS Tag = 0x42014E 353 | OPERATIONS Tag = 0x42014F 354 | RIGHT Tag = 0x420150 355 | ENDPOINT_ROLE Tag = 0x420151 356 | DEFAULTS_INFORMATION Tag = 0x420152 357 | OBJECT_DEFAULTS Tag = 0x420153 358 | EPHEMERAL Tag = 0x420154 359 | SERVER_HASHED_PASSWORD Tag = 0x420155 360 | ONE_TIME_PASSWORD Tag = 0x420156 361 | HASHED_PASSWORD Tag = 0x420157 362 | ADJUSTMENT_TYPE Tag = 0x420158 363 | PKCS11_INTERFACE Tag = 0x420159 364 | PKCS11_FUNCTION Tag = 0x42015A 365 | PKCS11_INPUT_PARAMETERS Tag = 0x42015B 366 | PKCS11_OUTPUT_PARAMETERS Tag = 0x42015C 367 | PKCS11_RETURN_CODE Tag = 0x42015D 368 | PROTECTION_STORAGE_MASK Tag = 0x42015E 369 | PROTECTION_STORAGE_MASKS Tag = 0x42015F 370 | INTEROP_FUNCTION Tag = 0x420160 371 | INTEROP_IDENTIFIER Tag = 0x420161 372 | ADJUSTMENT_VALUE Tag = 0x420162 373 | ) 374 | 375 | // KMIP Types 376 | const ( 377 | STRUCTURE Type = 0x01 378 | INTEGER Type = 0x02 379 | LONG_INTEGER Type = 0x03 380 | BIG_INTEGER Type = 0x04 381 | ENUMERATION Type = 0x05 382 | BOOLEAN Type = 0x06 383 | TEXT_STRING Type = 0x07 384 | BYTE_STRING Type = 0x08 385 | DATE_TIME Type = 0x09 386 | INTERVAL Type = 0x0A 387 | ) 388 | 389 | // KMIP Operations 390 | const ( 391 | // KMIP 1.0 392 | OPERATION_CREATE Enum = 0x00000001 393 | OPERATION_CREATE_KEY_PAIR Enum = 0x00000002 394 | OPERATION_REGISTER Enum = 0x00000003 395 | OPERATION_REKEY Enum = 0x00000004 396 | OPERATION_DERIVE_KEY Enum = 0x00000005 397 | OPERATION_CERTIFY Enum = 0x00000006 398 | OPERATION_RECERTIFY Enum = 0x00000007 399 | OPERATION_LOCATE Enum = 0x00000008 400 | OPERATION_CHECK Enum = 0x00000009 401 | OPERATION_GET Enum = 0x0000000A 402 | OPERATION_GET_ATTRIBUTES Enum = 0x0000000B 403 | OPERATION_GET_ATTRIBUTE_LIST Enum = 0x0000000C 404 | OPERATION_ADD_ATTRIBUTE Enum = 0x0000000D 405 | OPERATION_MODIFY_ATTRIBUTE Enum = 0x0000000E 406 | OPERATION_DELETE_ATTRIBUTE Enum = 0x0000000F 407 | OPERATION_OBTAIN_LEASE Enum = 0x00000010 408 | OPERATION_GET_USAGE_ALLOCATION Enum = 0x00000011 409 | OPERATION_ACTIVATE Enum = 0x00000012 410 | OPERATION_REVOKE Enum = 0x00000013 411 | OPERATION_DESTROY Enum = 0x00000014 412 | OPERATION_ARCHIVE Enum = 0x00000015 413 | OPERATION_RECOVER Enum = 0x00000016 414 | OPERATION_VALIDATE Enum = 0x00000017 415 | OPERATION_QUERY Enum = 0x00000018 416 | OPERATION_CANCEL Enum = 0x00000019 417 | OPERATION_POLL Enum = 0x0000001A 418 | OPERATION_NOTIFY Enum = 0x0000001B 419 | OPERATION_PUT Enum = 0x0000001C 420 | // KMIP 1.1 421 | OPERATION_REKEY_KEY_PAIR Enum = 0x0000001D 422 | OPERATION_DISCOVER_VERSIONS Enum = 0x0000001E 423 | // KMIP 1.2 424 | OPERATION_ENCRYPT Enum = 0x0000001F 425 | OPERATION_DECRYPT Enum = 0x00000020 426 | OPERATION_SIGN Enum = 0x00000021 427 | OPERATION_SIGNATURE_VERIFY Enum = 0x00000022 428 | OPERATION_MAC Enum = 0x00000023 429 | OPERATION_MAC_VERIFY Enum = 0x00000024 430 | OPERATION_RNG_RETRIEVE Enum = 0x00000025 431 | OPERATION_RNG_SEED Enum = 0x00000026 432 | OPERATION_HASH Enum = 0x00000027 433 | OPERATION_CREATE_SPLIT_KEY Enum = 0x00000028 434 | OPERATION_JOIN_SPLIT_KEY Enum = 0x00000029 435 | // KMIP 1.4 436 | OPERATION_IMPORT Enum = 0x0000002A 437 | OPERATION_EXPORT Enum = 0x0000002B 438 | // KMIP 2.0 439 | OPERATION_LOG Enum = 0x0000002C 440 | OPERATION_LOGIN Enum = 0x0000002D 441 | OPERATION_LOGOUT Enum = 0x0000002E 442 | OPERATION_DELEGATED_LOGIN Enum = 0x0000002F 443 | OPERATION_ADJUST_ATTRIBUTE Enum = 0x00000030 444 | OPERATION_SET_ATTRIBUTE Enum = 0x00000031 445 | OPERATION_SET_ENDPOINT_ROLE Enum = 0x00000032 446 | OPERATION_PKCS_11 Enum = 0x00000033 447 | OPERATION_INTEROP Enum = 0x00000034 448 | OPERATION_REPROVISION Enum = 0x00000035 449 | ) 450 | 451 | // KMIP Object Types 452 | const ( 453 | // KMIP 1.0 454 | OBJECT_TYPE_CERTIFICATE Enum = 0x00000001 455 | OBJECT_TYPE_SYMMETRIC_KEY Enum = 0x00000002 456 | OBJECT_TYPE_PUBLIC_KEY Enum = 0x00000003 457 | OBJECT_TYPE_PRIVATE_KEY Enum = 0x00000004 458 | OBJECT_TYPE_SPLIT_KEY Enum = 0x00000005 459 | OBJECT_TYPE_TEMPLATE Enum = 0x00000006 // Deprecated in KMIP 1.3, designated '(Reserved)' in KMIP 2.0 460 | OBJECT_TYPE_SECRET_DATA Enum = 0x00000007 461 | OBJECT_TYPE_OPAQUE_DATA Enum = 0x00000008 462 | // KMIP 1.2 463 | OBJECT_TYPE_PGP_KEY Enum = 0x00000009 464 | // KMIP 2.0 465 | OBJECT_TYPE_CERTIFICATE_REQUEST Enum = 0x0000000A 466 | ) 467 | 468 | // KMIP States 469 | const ( 470 | // KMIP 1.0 471 | STATE_PRE_ACTIVE Enum = 0x00000001 472 | STATE_ACTIVE Enum = 0x00000002 473 | STATE_DEACTIVATED Enum = 0x00000003 474 | STATE_COMPROMISED Enum = 0x00000004 475 | STATE_DESTROYED Enum = 0x00000005 476 | STATE_DESTROYED_COMPROMISED Enum = 0x00000006 477 | ) 478 | 479 | // KMIP Key Formats 480 | const ( 481 | // KMIP 1.0 482 | KEY_FORMAT_RAW Enum = 0x00000001 483 | KEY_FORMAT_OPAQUE Enum = 0x00000002 484 | KEY_FORMAT_PKCS_1 Enum = 0x00000003 485 | KEY_FORMAT_PKCS_8 Enum = 0x00000004 486 | KEY_FORMAT_X_509 Enum = 0x00000005 487 | KEY_FORMAT_EC_PRIVATE_KEY Enum = 0x00000006 488 | KEY_FORMAT_TRANSPARENT_SYMMETRIC_KEY Enum = 0x00000007 489 | KEY_FORMAT_TRANSPARENT_DSA_PRIVATE_KEY Enum = 0x00000008 490 | KEY_FORMAT_TRANSPARENT_DSA_PUBLIC_KEY Enum = 0x00000009 491 | KEY_FORMAT_TRANSPARENT_RSA_PRIVATE_KEY Enum = 0x0000000A 492 | KEY_FORMAT_TRANSPARENT_RSA_PUBLIC_KEY Enum = 0x0000000B 493 | KEY_FORMAT_TRANSPARENT_DH_PRIVATE_KEY Enum = 0x0000000C 494 | KEY_FORMAT_TRANSPARENT_DH_PUBLIC_KEY Enum = 0x0000000D 495 | KEY_FORMAT_TRANSPARENT_ECDSA_PRIVATE_KEY Enum = 0x0000000E // Deprecated in KMIP 1.4, designated '(Reserved)' in KMIP 2.0 496 | KEY_FORMAT_TRANSPARENT_ECDSA_PUBLIC_KEY Enum = 0x0000000F // Deprecated in KMIP 1.4, designated '(Reserved)' in KMIP 2.0 497 | KEY_FORMAT_TRANSPARENT_ECDH_PRIVATE_KEY Enum = 0x00000010 // Deprecated in KMIP 1.4, designated '(Reserved)' in KMIP 2.0 498 | KEY_FORMAT_TRANSPARENT_ECDH_PUBLIC_KEY Enum = 0x00000011 // Deprecated in KMIP 1.4, designated '(Reserved)' in KMIP 2.0 499 | KEY_FORMAT_TRANSPARENT_ECMQV_PRIVATE_KEY Enum = 0x00000012 // Deprecated in KMIP 1.4, designated '(Reserved)' in KMIP 2.0 500 | KEY_FORMAT_TRANSPARENT_ECMQV_PUBLIC_KEY Enum = 0x00000013 // Deprecated in KMIP 1.4, designated '(Reserved)' in KMIP 2.0 501 | // KMIP 1.3 502 | KEY_FORMAT_TRANSPARENT_EC_PRIVATE_KEY Enum = 0x00000014 503 | KEY_FORMAT_TRANSPARENT_EC_PUBLIC_KEY Enum = 0x00000015 504 | // KMIP 1.4 505 | KEY_FORMAT_PKCS_12 Enum = 0x00000016 506 | ) 507 | 508 | // KMIP Key Wrap Types 509 | const ( 510 | KEY_WRAP_NOT_WRAPPED Enum = 0x00000001 511 | KEY_WRAP_AS_REGISTERED Enum = 0x00000002 512 | ) 513 | 514 | // KMIP Wrapping Methods 515 | const ( 516 | // KMIP 1.0 517 | WRAPPING_METHOD_ENCRYPT Enum = 0x00000001 518 | WRAPPING_METHOD_MAC_SIGN Enum = 0x00000002 519 | WRAPPING_METHOD_ENCRYPT_THEN_MAC_SIGN Enum = 0x00000003 520 | WRAPPING_METHOD_MAC_SIGN_THEN_ENCRYPT Enum = 0x00000004 521 | WRAPPING_METHOD_TR_31 Enum = 0x00000005 522 | ) 523 | 524 | // KMIP Key Compression Types 525 | const ( 526 | // KMIP 1.0 527 | KEY_COMPRESSION_EC_PUBLIC_KEY_TYPE_UNCOMPRESSED Enum = 0x00000001 528 | KEY_COMPRESSION_EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_PRIME Enum = 0x00000002 529 | KEY_COMPRESSION_EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_CHAR2 Enum = 0x00000003 530 | KEY_COMPRESSION_EC_PUBLIC_KEY_TYPE_X9_62_HYBRID Enum = 0x00000004 531 | ) 532 | 533 | // KMIP Name Types 534 | const ( 535 | NAME_TYPE_UNINTERPRETED_TEXT_STRING Enum = 0x00000001 536 | NAME_TYPE_URI Enum = 0x00000002 537 | ) 538 | 539 | // KMIP Crypto Algorithms 540 | const ( 541 | // KMIP 1.0 542 | CRYPTO_DES Enum = 0x00000001 543 | CRYPTO_TRIPLE_DES Enum = 0x00000002 // '3DES' is invalid syntax 544 | CRYPTO_AES Enum = 0x00000003 545 | CRYPTO_RSA Enum = 0x00000004 546 | CRYPTO_DSA Enum = 0x00000005 547 | CRYPTO_ECDSA Enum = 0x00000006 548 | CRYPTO_HMAC_SHA1 Enum = 0x00000007 549 | CRYPTO_HMAC_SHA224 Enum = 0x00000008 550 | CRYPTO_HMAC_SHA256 Enum = 0x00000009 551 | CRYPTO_HMAC_SHA384 Enum = 0x0000000A 552 | CRYPTO_HMAC_SHA512 Enum = 0x0000000B 553 | CRYPTO_HMAC_MD5 Enum = 0x0000000C 554 | CRYPTO_DH Enum = 0x0000000D 555 | CRYPTO_ECDH Enum = 0x0000000E 556 | CRYPTO_ECMQV Enum = 0x0000000F 557 | CRYPTO_BLOWFISH Enum = 0x00000010 558 | CRYPTO_CAMELLIA Enum = 0x00000011 559 | CRYPTO_CAST5 Enum = 0x00000012 560 | CRYPTO_IDEA Enum = 0x00000013 561 | CRYPTO_MARS Enum = 0x00000014 562 | CRYPTO_RC2 Enum = 0x00000015 563 | CRYPTO_RC4 Enum = 0x00000016 564 | CRYPTO_RC5 Enum = 0x00000017 565 | CRYPTO_SKIPJACK Enum = 0x00000018 566 | CRYPTO_TWOFISH Enum = 0x00000019 567 | // KMIP 1.2 568 | CRYPTO_EC Enum = 0x0000001A 569 | // KMIP 1.3 570 | CRYPTO_ONE_TIME_PAD Enum = 0x0000001B 571 | // KMIP 1.4 572 | CRYPTO_CHACHA20 Enum = 0x0000001C 573 | CRYPTO_POLY1305 Enum = 0x0000001D 574 | CRYPTO_CHACHA20_POLY1305 Enum = 0x0000001E 575 | CRYPTO_SHA3_224 Enum = 0x0000001F 576 | CRYPTO_SHA3_256 Enum = 0x00000020 577 | CRYPTO_SHA3_384 Enum = 0x00000021 578 | CRYPTO_SHA3_512 Enum = 0x00000022 579 | CRYPTO_HMAC_SHA3_224 Enum = 0x00000023 580 | CRYPTO_HMAC_SHA3_256 Enum = 0x00000024 581 | CRYPTO_HMAC_SHA3_384 Enum = 0x00000025 582 | CRYPTO_HMAC_SHA3_512 Enum = 0x00000026 583 | CRYPTO_SHAKE_128 Enum = 0x00000027 584 | CRYPTO_SHAKE_256 Enum = 0x00000028 585 | // KMIP 2.0 586 | CRYPTO_ARIA Enum = 0x00000029 587 | CRYPTO_SEED Enum = 0x0000002A 588 | CRYPTO_SM2 Enum = 0x0000002B 589 | CRYPTO_SM3 Enum = 0x0000002C 590 | CRYPTO_SM4 Enum = 0x0000002D 591 | CRYPTO_GOST_R_34_10_2012 Enum = 0x0000002E 592 | CRYPTO_GOST_R_34_11_2012 Enum = 0x0000002F 593 | CRYPTO_GOST_R_34_13_2015 Enum = 0x00000030 594 | CRYPTO_GOST_28147_89 Enum = 0x00000031 595 | CRYPTO_XMSS Enum = 0x00000032 596 | CRYPTO_SPHINCS_256 Enum = 0x00000033 597 | CRYPTO_MCELIECE Enum = 0x00000034 598 | CRYPTO_MCELIECE_6960119 Enum = 0x00000035 599 | CRYPTO_MCELIECE_8192128 Enum = 0x00000036 600 | CRYPTO_ED25519 Enum = 0x00000037 601 | CRYPTO_ED448 Enum = 0x00000038 602 | ) 603 | 604 | // KMIP Padding Method Enumeration 605 | const ( 606 | // KMIP 1.0 607 | PADDING_METHOD_NONE Enum = 0x00000001 608 | PADDING_METHOD_OAEP Enum = 0x00000002 609 | PADDING_METHOD_PKCS_5 Enum = 0x00000003 610 | PADDING_METHOD_SSL_3 Enum = 0x00000004 611 | PADDING_METHOD_ZEROS Enum = 0x00000005 612 | PADDING_METHOD_ANSI_X9_23 Enum = 0x00000006 613 | PADDING_METHOD_ISO_10126 Enum = 0x00000007 614 | PADDING_METHOD_PKCS_1_V1_5 Enum = 0x00000008 615 | PADDING_METHOD_X9_31 Enum = 0x00000009 616 | PADDING_METHOD_PSS Enum = 0x0000000A 617 | ) 618 | 619 | // KMIP Hash Algorithms 620 | const ( 621 | // KMIP 1.0 622 | HASH_MD2 Enum = 0x00000001 623 | HASH_MD4 Enum = 0x00000002 624 | HASH_MD5 Enum = 0x00000003 625 | HASH_SHA1 Enum = 0x00000004 626 | HASH_SHA224 Enum = 0x00000005 627 | HASH_SHA256 Enum = 0x00000006 628 | HASH_SHA384 Enum = 0x00000007 629 | HASH_SHA512 Enum = 0x00000008 630 | HASH_RIPEMD_160 Enum = 0x00000009 631 | HASH_TIGER Enum = 0x0000000A 632 | HASH_WHIRLPOOL Enum = 0x0000000B 633 | // KMIP 1.2 634 | HASH_SHA512_224 Enum = 0x0000000C 635 | HASH_SHA512_256 Enum = 0x0000000D 636 | // KMIP 1.4 637 | HASH_SHA3_224 Enum = 0x0000000E 638 | HASH_SHA3_256 Enum = 0x0000000F 639 | HASH_SHA3_384 Enum = 0x00000010 640 | HASH_SHA3_512 Enum = 0x00000011 641 | ) 642 | 643 | // KMIP Credential Type 644 | const ( 645 | // KMIP 1.0 646 | CREDENTIAL_TYPE_USERNAME_AND_PASSWORD Enum = 0x00000001 647 | // KMIP 1.1 648 | CREDENTIAL_TYPE_DEVICE Enum = 0x00000002 649 | // KMIP 1.2 650 | CREDENTIAL_TYPE_ATTESTATION Enum = 0x00000003 651 | // KMIP 2.0 652 | CREDENTIAL_TYPE_ONE_TIME_PASSWORD Enum = 0x00000004 653 | CREDENTIAL_TYPE_HASHED_PASSWORD Enum = 0x00000005 654 | CREDENTIAL_TYPE_TICKET Enum = 0x00000006 655 | ) 656 | 657 | // KMIP Result Status 658 | const ( 659 | RESULT_STATUS_SUCCESS Enum = 0x00000000 660 | RESULT_STATUS_OPERATION_FAILED Enum = 0x00000001 661 | RESULT_STATUS_OPERATION_PENDING Enum = 0x00000002 662 | RESULT_STATUS_OPERATION_UNDONE Enum = 0x00000003 663 | ) 664 | 665 | // KMIP Result Reason 666 | const ( 667 | // KMIP 1.0 668 | RESULT_REASON_ITEM_NOT_FOUND Enum = 0x00000001 669 | RESULT_REASON_RESPONSE_TOO_LARGE Enum = 0x00000002 670 | RESULT_REASON_AUTHENTICATION_NOT_SUCCESSFUL Enum = 0x00000003 671 | RESULT_REASON_INVALID_MESSAGE Enum = 0x00000004 672 | RESULT_REASON_OPERATION_NOT_SUPPORTED Enum = 0x00000005 673 | RESULT_REASON_MISSING_DATA Enum = 0x00000006 674 | RESULT_REASON_INVALID_FIELD Enum = 0x00000007 675 | RESULT_REASON_FEATURE_NOT_SUPPORTED Enum = 0x00000008 676 | RESULT_REASON_OPERATION_CANCELED_BY_REQUESTER Enum = 0x00000009 677 | RESULT_REASON_CRYPTOGRAPHIC_FAILURE Enum = 0x0000000A 678 | RESULT_REASON_ILLEGAL_OPERATION Enum = 0x0000000B 679 | RESULT_REASON_PERMISSION_DENIED Enum = 0x0000000C 680 | RESULT_REASON_OBJECT_ARCHIVED Enum = 0x0000000D 681 | RESULT_REASON_INDEX_OUT_OF_BOUNDS Enum = 0x0000000E 682 | RESULT_REASON_APPLICATION_NAMESPACE_NOT_SUPPORTED Enum = 0x0000000F 683 | RESULT_REASON_KEY_FORMAT_TYPE_NOT_SUPPORTED Enum = 0x00000010 684 | RESULT_REASON_KEY_COMPRESSION_TYPE_NOT_SUPPORTED Enum = 0x00000011 685 | RESULT_REASON_ENCODING_OPTION_ERROR Enum = 0x00000012 686 | RESULT_REASON_KEY_VALUE_NOT_PRESENT Enum = 0x00000013 687 | RESULT_REASON_ATTESTATION_REQUIRED Enum = 0x00000014 688 | RESULT_REASON_ATTESTATION_FAILED Enum = 0x00000015 689 | RESULT_REASON_SENSITIVE Enum = 0x00000016 690 | RESULT_REASON_NOT_EXTRACTABLE Enum = 0x00000017 691 | RESULT_REASON_OBJECT_ALREADY_EXISTS Enum = 0x00000018 692 | RESULT_REASON_GENERAL_FAILURE Enum = 0x00000100 693 | // KMIP 2.0 694 | RESULT_REASON_INVALID_TICKET Enum = 0x00000019 695 | RESULT_REASON_USAGE_LIMIT_EXCEEDED Enum = 0x0000001A 696 | RESULT_REASON_NUMERIC_RANGE Enum = 0x0000001B 697 | RESULT_REASON_INVALID_DATA_TYPE Enum = 0x0000001C 698 | RESULT_REASON_READ_ONLY_ATTRIBUTE Enum = 0x0000001D 699 | RESULT_REASON_MULTI_VALUED_ATTRIBUTE Enum = 0x0000001E 700 | RESULT_REASON_UNSUPPORTED_ATTRIBUTE Enum = 0x0000001F 701 | RESULT_REASON_ATTRIBUTE_INSTANCE_NOT_FOUND Enum = 0x00000020 702 | RESULT_REASON_ATTRIBUTE_NOT_FOUND Enum = 0x00000021 703 | RESULT_REASON_ATTRIBUTE_READ_ONLY Enum = 0x00000022 704 | RESULT_REASON_ATTRIBUTE_SINGLE_VALUED Enum = 0x00000023 705 | RESULT_REASON_BAD_CRYPTOGRAPHIC_PARAMETERS Enum = 0x00000024 706 | RESULT_REASON_BAD_PASSWORD Enum = 0x00000025 707 | RESULT_REASON_CODEC_ERROR Enum = 0x00000026 708 | // 0x00000027 is designated '(Reserved)' in KMIP 2.0 709 | RESULT_REASON_ILLEGAL_OBJECT_TYPE Enum = 0x00000028 710 | RESULT_REASON_INCOMPATIBLE_CRYPTOGRAPHIC_USAGE_MASK Enum = 0x00000029 711 | RESULT_REASON_INTERNAL_SERVER_ERROR Enum = 0x0000002A 712 | RESULT_REASON_INVALID_ASYNCHRONOUS_CORRELATION_VALUE Enum = 0x0000002B 713 | RESULT_REASON_INVALID_ATTRIBUTE Enum = 0x0000002C 714 | RESULT_REASON_INVALID_ATTRIBUTE_VALUE Enum = 0x0000002D 715 | RESULT_REASON_INVALID_CORRELATION_VALUE Enum = 0x0000002E 716 | RESULT_REASON_INVALID_CSR Enum = 0x0000002F 717 | RESULT_REASON_INVALID_OBJECT_TYPE Enum = 0x00000030 718 | // 0x00000031 is designated '(Reserved)' in KMIP 2.0 719 | RESULT_REASON_KEY_WRAP_TYPE_NOT_SUPPORTED Enum = 0x00000032 720 | // 0x00000033 is designated '(Reserved)' in KMIP 2.0 721 | RESULT_REASON_MISSING_INITIALIZATION_VECTOR Enum = 0x00000034 722 | RESULT_REASON_NON_UNIQUE_NAME_ATTRIBUTE Enum = 0x00000035 723 | RESULT_REASON_OBJECT_DESTROYED Enum = 0x00000036 724 | RESULT_REASON_OBJECT_NOT_FOUND Enum = 0x00000037 725 | // 0x00000038 is unassigned 726 | RESULT_REASON_NOT_AUTHORISED Enum = 0x00000039 727 | RESULT_REASON_SERVER_LIMIT_EXCEEDED Enum = 0x0000003A 728 | RESULT_REASON_UNKNOWN_ENUMERATION Enum = 0x0000003B 729 | RESULT_REASON_UNKNOWN_MESSAGE_EXTENSION Enum = 0x0000003C 730 | RESULT_REASON_UNKNOWN_TAG Enum = 0x0000003D 731 | RESULT_REASON_UNSUPPORTED_CRYPTOGRAPHIC_PARAMETERS Enum = 0x0000003E 732 | RESULT_REASON_UNSUPPORTED_PROTOCOL_VERSION Enum = 0x0000003F 733 | RESULT_REASON_WRAPPING_OBJECT_ARCHIVED Enum = 0x00000040 734 | RESULT_REASON_WRAPPING_OBJECT_DESTROYED Enum = 0x00000041 735 | RESULT_REASON_WRAPPING_OBJECT_NOT_FOUND Enum = 0x00000042 736 | RESULT_REASON_WRONG_KEY_LIFECYCLE_STATE Enum = 0x00000043 737 | RESULT_REASON_PROTECTION_STORAGE_UNAVAILABLE Enum = 0x00000044 738 | RESULT_REASON_PKCS11_CODEC_ERROR Enum = 0x00000045 739 | RESULT_REASON_PKCS11_INVALID_FUNCTION Enum = 0x00000046 740 | RESULT_REASON_PKCS11_INVALID_INTERFACE Enum = 0x00000047 741 | ) 742 | 743 | const ( 744 | REVOCATION_REASON_UNSPECIFIED Enum = 0x0000001 745 | REVOCATION_REASON_KEY_COMPROMISE Enum = 0x0000002 746 | REVOCATION_REASON_CA_COMPROMISE Enum = 0x0000003 747 | REVOCATION_REASON_AFFILIATION_CHANGED Enum = 0x0000004 748 | REVOCATION_REASON_SUPERSEDED Enum = 0x0000005 749 | REVOCATION_REASON_CESSATION_OF_OPERATION Enum = 0x0000006 750 | REVOCATION_REASON_PRIVILEGE_WITHDRAWN Enum = 0x0000007 751 | ) 752 | 753 | const ( 754 | CRYPTO_USAGE_MASK_SIGN Enum = 0x00000001 755 | CRYPTO_USAGE_MASK_VERIFY Enum = 0x00000002 756 | CRYPTO_USAGE_MASK_ENCRYPT Enum = 0x00000004 757 | CRYPTO_USAGE_MASK_DECRYPT Enum = 0x00000008 758 | CRYPTO_USAGE_MASK_WRAP_KEY Enum = 0x00000010 759 | CRYPTO_USAGE_MASK_UNWRAP_KEY Enum = 0x00000020 760 | CRYPTO_USAGE_MASK_EXPORT Enum = 0x00000040 761 | CRYPTO_USAGE_MASK_MAC_GENERATE Enum = 0x00000080 762 | CRYPTO_USAGE_MASK_MAC_VERIFY Enum = 0x00000100 763 | CRYPTO_USAGE_MASK_DERIVE_KEY Enum = 0x00000200 764 | CRYPTO_USAGE_MASK_CONTENT_COMMITMENT Enum = 0x00000400 765 | CRYPTO_USAGE_MASK_KEY_AGREEMENT Enum = 0x00000800 766 | CRYPTO_USAGE_MASK_CERTIFICATE_SIGN Enum = 0x00001000 767 | CRYPTO_USAGE_MASK_CRL_SIGN Enum = 0x00002000 768 | CRYPTO_USAGE_MASK_GENERATE_CRYPTOGRAM Enum = 0x00004000 769 | CRYPTO_USAGE_MASK_VALIDATE_CRYPTOGRAM Enum = 0x00008000 770 | CRYPTO_USAGE_MASK_TRANSLATE_ENCRYPT Enum = 0x00010000 771 | CRYPTO_USAGE_MASK_TRANSLATE_DECRYPT Enum = 0x00020000 772 | CRYPTO_USAGE_MASK_TRANSLATE_WRAP Enum = 0x00040000 773 | CRYPTO_USAGE_MASK_TRANSLATE_UNWRAP Enum = 0x00080000 774 | ) 775 | 776 | // KMIP Block Cipher Mode Enumeration. 777 | const ( 778 | BLOCK_MODE_CBC Enum = 0x00000001 779 | BLOCK_MODE_ECB Enum = 0x00000002 780 | BLOCK_MODE_PCBC Enum = 0x00000003 781 | BLOCK_MODE_CFB Enum = 0x00000004 782 | BLOCK_MODE_OFB Enum = 0x00000005 783 | BLOCK_MODE_CTR Enum = 0x00000006 784 | BLOCK_MODE_CMAC Enum = 0x00000007 785 | BLOCK_MODE_CCM Enum = 0x00000008 786 | BLOCK_MODE_GCM Enum = 0x00000009 787 | BLOCK_MODE_CBC_MAC Enum = 0x0000000A 788 | BLOCK_MODE_XTS Enum = 0x0000000B 789 | BLOCK_MODE_AESKeyWrapPadding Enum = 0x0000000C 790 | BLOCK_MODE_NISTKeyWrap Enum = 0x0000000D 791 | BLOCK_MODE_X9_102_AESKW Enum = 0x0000000E 792 | BLOCK_MODE_X9_102_TDKW Enum = 0x0000000F 793 | BLOCK_MODE_X9_102_AKW1 Enum = 0x00000010 794 | BLOCK_MODE_X9_102_AKW2 Enum = 0x00000011 795 | BLOCK_MODE_AEAD Enum = 0x00000012 796 | ) 797 | 798 | // KMIP Attribute Names. 799 | const ( 800 | ATTRIBUTE_NAME_UNIQUE_IDENTIFIER = "Unique Identifier" 801 | ATTRIBUTE_NAME_NAME = "Name" 802 | ATTRIBUTE_NAME_OBJECT_TYPE = "Object Type" 803 | ATTRIBUTE_NAME_CRYPTOGRAPHIC_ALGORITHM = "Cryptographic Algorithm" 804 | ATTRIBUTE_NAME_CRYPTOGRAPHIC_LENGTH = "Cryptographic Length" 805 | ATTRIBUTE_NAME_CRYPTOGRAPHIC_PARAMETERS = "Cryptographic Parameters" 806 | ATTRIBUTE_NAME_CRYPTOGRAPHIC_DOMAIN_PARAMETERS = "Cryptographic Domain Parameters" 807 | ATTRIBUTE_NAME_CERTIFICATE_TYPE = "Certificate Type" 808 | ATTRIBUTE_NAME_CERTIFICATE_LENGTH = "Certificate Length" 809 | ATTRIBUTE_NAME_X_509_CERTIFICATE_IDENTIFIER = "X.509 Certificate Identifier" 810 | ATTRIBUTE_NAME_X_509_CERTIFICATE_SUBJECT = "X.509 Certificate Subject" 811 | ATTRIBUTE_NAME_X_509_CERTIFICATE_ISSUER = "X.509 Certificate Issuer" 812 | ATTRIBUTE_NAME_CERTIFICATE_IDENTIFIER = "Certificate Identifier" 813 | ATTRIBUTE_NAME_CERTIFICATE_SUBJECT = "Certificate Subject" 814 | ATTRIBUTE_NAME_CERTIFICATE_ISSUER = "Certificate Issuer" 815 | ATTRIBUTE_NAME_DIGITAL_SIGNATURE_ALGORITHM = "Digital Signature Algorithm" 816 | ATTRIBUTE_NAME_DIGEST = "Digest" 817 | ATTRIBUTE_NAME_OPERATION_POLICY_NAME = "Operation Policy Name" 818 | ATTRIBUTE_NAME_CRYPTOGRAPHIC_USAGE_MASK = "Cryptographic Usage Mask" 819 | ATTRIBUTE_NAME_LEASE_TIME = "Lease Time" 820 | ATTRIBUTE_NAME_USAGE_LIMITS = "Usage Limits" 821 | ATTRIBUTE_NAME_STATE = "State" 822 | ATTRIBUTE_NAME_INITIAL_DATE = "Initial Date" 823 | ATTRIBUTE_NAME_ACTIVATION_DATE = "Activation Date" 824 | ATTRIBUTE_NAME_PROCESS_START_DATE = "Process Start Date" 825 | ATTRIBUTE_NAME_PROTECT_STOP_DATE = "Protect Stop Date" 826 | ATTRIBUTE_NAME_DEACTIVATION_DATE = "Deactivation Date" 827 | ATTRIBUTE_NAME_DESTROY_DATE = "Destroy Date" 828 | ATTRIBUTE_NAME_COMPROMISE_OCCURRENCE_DATE = "Compromise Occurrence Date" 829 | ATTRIBUTE_NAME_COMPROMISE_DATE = "Compromise Date" 830 | ATTRIBUTE_NAME_REVOCATION_REASON = "Revocation Reason" 831 | ATTRIBUTE_NAME_ARCHIVE_DATE = "Archive Date" 832 | ATTRIBUTE_NAME_OBJECT_GROUP = "Object Group" 833 | ATTRIBUTE_NAME_FRESH = "Fresh" 834 | ATTRIBUTE_NAME_LINK = "Link" 835 | ATTRIBUTE_NAME_APPLICATION_SPECIFIC_INFORMATION = "Application Specific Information" 836 | ATTRIBUTE_NAME_CONTACT_INFORMATION = "Contact Information" 837 | ATTRIBUTE_NAME_LAST_CHANGE_DATE = "Last Change Date" 838 | ATTRIBUTE_NAME_CUSTOM_ATTRIBUTE = "Custom Attribute" 839 | ATTRIBUTE_NAME_ALTERNATIVE_NAME = "Alternative Name" 840 | ATTRIBUTE_NAME_KEY_VALUE_PRESENT = "Key Value Present" 841 | ATTRIBUTE_NAME_KEY_VALUE_LOCATION = "Key Value Location" 842 | ATTRIBUTE_NAME_ORIGINAL_CREATION_DATE = "Original Creation Date" 843 | ) 844 | 845 | var tagMap = map[string]Tag{ 846 | "-": ANY_TAG, 847 | "ANY_TAG": ANY_TAG, 848 | "ACTIVATION_DATE": ACTIVATION_DATE, 849 | "APPLICATION_DATA": APPLICATION_DATA, 850 | "APPLICATION_NAMESPACE": APPLICATION_NAMESPACE, 851 | "APPLICATION_SPECIFIC_INFORMATION": APPLICATION_SPECIFIC_INFORMATION, 852 | "ARCHIVE_DATE": ARCHIVE_DATE, 853 | "ASYNCHRONOUS_CORRELATION_VALUE": ASYNCHRONOUS_CORRELATION_VALUE, 854 | "ASYNCHRONOUS_INDICATOR": ASYNCHRONOUS_INDICATOR, 855 | "ATTRIBUTE": ATTRIBUTE, 856 | "ATTRIBUTE_INDEX": ATTRIBUTE_INDEX, 857 | "ATTRIBUTE_NAME": ATTRIBUTE_NAME, 858 | "ATTRIBUTE_VALUE": ATTRIBUTE_VALUE, 859 | "AUTHENTICATION": AUTHENTICATION, 860 | "BATCH_COUNT": BATCH_COUNT, 861 | "BATCH_ERROR_CONTINUATION_OPTION": BATCH_ERROR_CONTINUATION_OPTION, 862 | "BATCH_ITEM": BATCH_ITEM, 863 | "BATCH_ORDER_OPTION": BATCH_ORDER_OPTION, 864 | "BLOCK_CIPHER_MODE": BLOCK_CIPHER_MODE, 865 | "CANCELLATION_RESULT": CANCELLATION_RESULT, 866 | "CERTIFICATE": CERTIFICATE, 867 | "CERTIFICATE_IDENTIFIER": CERTIFICATE_IDENTIFIER, 868 | "CERTIFICATE_ISSUER": CERTIFICATE_ISSUER, 869 | "CERTIFICATE_ISSUER_ALTERNATIVE_NAME": CERTIFICATE_ISSUER_ALTERNATIVE_NAME, 870 | "CERTIFICATE_ISSUER_DISTINGUISHED_NAME": CERTIFICATE_ISSUER_DISTINGUISHED_NAME, 871 | "CERTIFICATE_REQUEST": CERTIFICATE_REQUEST, 872 | "CERTIFICATE_REQUEST_TYPE": CERTIFICATE_REQUEST_TYPE, 873 | "CERTIFICATE_SUBJECT": CERTIFICATE_SUBJECT, 874 | "CERTIFICATE_SUBJECT_ALTERNATIVE_NAME": CERTIFICATE_SUBJECT_ALTERNATIVE_NAME, 875 | "CERTIFICATE_SUBJECT_DISTINGUISHED_NAME": CERTIFICATE_SUBJECT_DISTINGUISHED_NAME, 876 | "CERTIFICATE_TYPE": CERTIFICATE_TYPE, 877 | "CERTIFICATE_VALUE": CERTIFICATE_VALUE, 878 | "COMMON_TEMPLATE_ATTRIBUTE": COMMON_TEMPLATE_ATTRIBUTE, 879 | "COMPROMISE_DATE": COMPROMISE_DATE, 880 | "COMPROMISE_OCCURRENCE_DATE": COMPROMISE_OCCURRENCE_DATE, 881 | "CONTACT_INFORMATION": CONTACT_INFORMATION, 882 | "CREDENTIAL": CREDENTIAL, 883 | "CREDENTIAL_TYPE": CREDENTIAL_TYPE, 884 | "CREDENTIAL_VALUE": CREDENTIAL_VALUE, 885 | "CRITICALITY_INDICATOR": CRITICALITY_INDICATOR, 886 | "CRT_COEFFICIENT": CRT_COEFFICIENT, 887 | "CRYPTOGRAPHIC_ALGORITHM": CRYPTOGRAPHIC_ALGORITHM, 888 | "CRYPTOGRAPHIC_DOMAIN_PARAMETERS": CRYPTOGRAPHIC_DOMAIN_PARAMETERS, 889 | "CRYPTOGRAPHIC_LENGTH": CRYPTOGRAPHIC_LENGTH, 890 | "CRYPTOGRAPHIC_PARAMETERS": CRYPTOGRAPHIC_PARAMETERS, 891 | "CRYPTOGRAPHIC_USAGE_MASK": CRYPTOGRAPHIC_USAGE_MASK, 892 | "CUSTOM_ATTRIBUTE": CUSTOM_ATTRIBUTE, 893 | "D": D, 894 | "DEACTIVATION_DATE": DEACTIVATION_DATE, 895 | "DERIVATION_DATA": DERIVATION_DATA, 896 | "DERIVATION_METHOD": DERIVATION_METHOD, 897 | "DERIVATION_PARAMETERS": DERIVATION_PARAMETERS, 898 | "DESTROY_DATE": DESTROY_DATE, 899 | "DIGEST": DIGEST, 900 | "DIGEST_VALUE": DIGEST_VALUE, 901 | "ENCRYPTION_KEY_INFORMATION": ENCRYPTION_KEY_INFORMATION, 902 | "G": G, 903 | "HASHING_ALGORITHM": HASHING_ALGORITHM, 904 | "INITIAL_DATE": INITIAL_DATE, 905 | "INITIALIZATION_VECTOR": INITIALIZATION_VECTOR, 906 | "ISSUER": ISSUER, 907 | "ITERATION_COUNT": ITERATION_COUNT, 908 | "IV_COUNTER_NONCE": IV_COUNTER_NONCE, 909 | "J": J, 910 | "KEY": KEY, 911 | "KEY_BLOCK": KEY_BLOCK, 912 | "KEY_COMPRESSION_TYPE": KEY_COMPRESSION_TYPE, 913 | "KEY_FORMAT_TYPE": KEY_FORMAT_TYPE, 914 | "KEY_MATERIAL": KEY_MATERIAL, 915 | "KEY_PART_IDENTIFIER": KEY_PART_IDENTIFIER, 916 | "KEY_VALUE": KEY_VALUE, 917 | "KEY_WRAPPING_DATA": KEY_WRAPPING_DATA, 918 | "KEY_WRAPPING_SPECIFICATION": KEY_WRAPPING_SPECIFICATION, 919 | "LAST_CHANGE_DATE": LAST_CHANGE_DATE, 920 | "LEASE_TIME": LEASE_TIME, 921 | "LINK": LINK, 922 | "LINK_TYPE": LINK_TYPE, 923 | "LINKED_OBJECT_IDENTIFIER": LINKED_OBJECT_IDENTIFIER, 924 | "MAC_SIGNATURE": MAC_SIGNATURE, 925 | "MAC_SIGNATURE_KEY_INFORMATION": MAC_SIGNATURE_KEY_INFORMATION, 926 | "MAXIMUM_ITEMS": MAXIMUM_ITEMS, 927 | "MAXIMUM_RESPONSE_SIZE": MAXIMUM_RESPONSE_SIZE, 928 | "MESSAGE_EXTENSION": MESSAGE_EXTENSION, 929 | "MODULUS": MODULUS, 930 | "NAME": NAME, 931 | "NAME_TYPE": NAME_TYPE, 932 | "NAME_VALUE": NAME_VALUE, 933 | "OBJECT_GROUP": OBJECT_GROUP, 934 | "OBJECT_TYPE": OBJECT_TYPE, 935 | "OFFSET": OFFSET, 936 | "OPAQUE_DATA_TYPE": OPAQUE_DATA_TYPE, 937 | "OPAQUE_DATA_VALUE": OPAQUE_DATA_VALUE, 938 | "OPAQUE_OBJECT": OPAQUE_OBJECT, 939 | "OPERATION": OPERATION, 940 | "OPERATION_POLICY_NAME": OPERATION_POLICY_NAME, 941 | "P": P, 942 | "PADDING_METHOD": PADDING_METHOD, 943 | "PRIME_EXPONENT_P": PRIME_EXPONENT_P, 944 | "PRIME_EXPONENT_Q": PRIME_EXPONENT_Q, 945 | "PRIME_FIELD_SIZE": PRIME_FIELD_SIZE, 946 | "PRIVATE_EXPONENT": PRIVATE_EXPONENT, 947 | "PRIVATE_KEY": PRIVATE_KEY, 948 | "PRIVATE_KEY_TEMPLATE_ATTRIBUTE": PRIVATE_KEY_TEMPLATE_ATTRIBUTE, 949 | "PRIVATE_KEY_UNIQUE_IDENTIFIER": PRIVATE_KEY_UNIQUE_IDENTIFIER, 950 | "PROCESS_START_DATE": PROCESS_START_DATE, 951 | "PROTECT_STOP_DATE": PROTECT_STOP_DATE, 952 | "PROTOCOL_VERSION": PROTOCOL_VERSION, 953 | "PROTOCOL_VERSION_MAJOR": PROTOCOL_VERSION_MAJOR, 954 | "PROTOCOL_VERSION_MINOR": PROTOCOL_VERSION_MINOR, 955 | "PUBLIC_EXPONENT": PUBLIC_EXPONENT, 956 | "PUBLIC_KEY": PUBLIC_KEY, 957 | "PUBLIC_KEY_TEMPLATE_ATTRIBUTE": PUBLIC_KEY_TEMPLATE_ATTRIBUTE, 958 | "PUBLIC_KEY_UNIQUE_IDENTIFIER": PUBLIC_KEY_UNIQUE_IDENTIFIER, 959 | "PUT_FUNCTION": PUT_FUNCTION, 960 | "Q": Q, 961 | "Q_STRING": Q_STRING, 962 | "QLENGTH": QLENGTH, 963 | "QUERY_FUNCTION": QUERY_FUNCTION, 964 | "RECOMMENDED_CURVE": RECOMMENDED_CURVE, 965 | "REPLACED_UNIQUE_IDENTIFIER": REPLACED_UNIQUE_IDENTIFIER, 966 | "REQUEST_BATCH_ITEM": REQUEST_BATCH_ITEM, 967 | "REQUEST_HEADER": REQUEST_HEADER, 968 | "REQUEST_MESSAGE": REQUEST_MESSAGE, 969 | "REQUEST_PAYLOAD": REQUEST_PAYLOAD, 970 | "RESPONSE_BATCH_ITEM": RESPONSE_BATCH_ITEM, 971 | "RESPONSE_HEADER": RESPONSE_HEADER, 972 | "RESPONSE_MESSAGE": RESPONSE_MESSAGE, 973 | "RESPONSE_PAYLOAD": RESPONSE_PAYLOAD, 974 | "RESULT_MESSAGE": RESULT_MESSAGE, 975 | "RESULT_REASON": RESULT_REASON, 976 | "RESULT_STATUS": RESULT_STATUS, 977 | "REVOCATION_MESSAGE": REVOCATION_MESSAGE, 978 | "REVOCATION_REASON": REVOCATION_REASON, 979 | "REVOCATION_REASON_CODE": REVOCATION_REASON_CODE, 980 | "KEY_ROLE_TYPE": KEY_ROLE_TYPE, 981 | "SALT": SALT, 982 | "SECRET_DATA": SECRET_DATA, 983 | "SECRET_DATA_TYPE": SECRET_DATA_TYPE, 984 | "SERIAL_NUMBER": SERIAL_NUMBER, 985 | "SERVER_INFORMATION": SERVER_INFORMATION, 986 | "SPLIT_KEY": SPLIT_KEY, 987 | "SPLIT_KEY_METHOD": SPLIT_KEY_METHOD, 988 | "SPLIT_KEY_PARTS": SPLIT_KEY_PARTS, 989 | "SPLIT_KEY_THRESHOLD": SPLIT_KEY_THRESHOLD, 990 | "STATE": STATE, 991 | "STORAGE_STATUS_MASK": STORAGE_STATUS_MASK, 992 | "SYMMETRIC_KEY": SYMMETRIC_KEY, 993 | "TEMPLATE": TEMPLATE, 994 | "TEMPLATE_ATTRIBUTE": TEMPLATE_ATTRIBUTE, 995 | "TIME_STAMP": TIME_STAMP, 996 | "UNIQUE_BATCH_ITEM_ID": UNIQUE_BATCH_ITEM_ID, 997 | "UNIQUE_IDENTIFIER": UNIQUE_IDENTIFIER, 998 | "USAGE_LIMITS": USAGE_LIMITS, 999 | "USAGE_LIMITS_COUNT": USAGE_LIMITS_COUNT, 1000 | "USAGE_LIMITS_TOTAL": USAGE_LIMITS_TOTAL, 1001 | "USAGE_LIMITS_UNIT": USAGE_LIMITS_UNIT, 1002 | "USERNAME": USERNAME, 1003 | "VALIDITY_DATE": VALIDITY_DATE, 1004 | "VALIDITY_INDICATOR": VALIDITY_INDICATOR, 1005 | "VENDOR_EXTENSION": VENDOR_EXTENSION, 1006 | "VENDOR_IDENTIFICATION": VENDOR_IDENTIFICATION, 1007 | "WRAPPING_METHOD": WRAPPING_METHOD, 1008 | "X": X, 1009 | "Y": Y, 1010 | "PASSWORD": PASSWORD, 1011 | "DEVICE_IDENTIFIER": DEVICE_IDENTIFIER, 1012 | "ENCODING_OPTION": ENCODING_OPTION, 1013 | "EXTENSION_INFORMATION": EXTENSION_INFORMATION, 1014 | "EXTENSION_NAME": EXTENSION_NAME, 1015 | "EXTENSION_TAG": EXTENSION_TAG, 1016 | "EXTENSION_TYPE": EXTENSION_TYPE, 1017 | "FRESH": FRESH, 1018 | "MACHINE_IDENTIFIER": MACHINE_IDENTIFIER, 1019 | "MEDIA_IDENTIFIER": MEDIA_IDENTIFIER, 1020 | "NETWORK_IDENTIFIER": NETWORK_IDENTIFIER, 1021 | "OBJECT_GROUP_MEMBER": OBJECT_GROUP_MEMBER, 1022 | "CERTIFICATE_LENGTH": CERTIFICATE_LENGTH, 1023 | "DIGITAL_SIGNATURE_ALGORITHM": DIGITAL_SIGNATURE_ALGORITHM, 1024 | "CERTIFICATE_SERIAL_NUMBER": CERTIFICATE_SERIAL_NUMBER, 1025 | "DEVICE_SERIAL_NUMBER": DEVICE_SERIAL_NUMBER, 1026 | "ISSUER_ALTERNATIVE_NAME": ISSUER_ALTERNATIVE_NAME, 1027 | "ISSUER_DISTINGUISHED_NAME": ISSUER_DISTINGUISHED_NAME, 1028 | "SUBJECT_ALTERNATIVE_NAME": SUBJECT_ALTERNATIVE_NAME, 1029 | "SUBJECT_DISTINGUISHED_NAME": SUBJECT_DISTINGUISHED_NAME, 1030 | "X_509_CERTIFICATE_IDENTIFIER": X_509_CERTIFICATE_IDENTIFIER, 1031 | "X_509_CERTIFICATE_ISSUER": X_509_CERTIFICATE_ISSUER, 1032 | "X_509_CERTIFICATE_SUBJECT": X_509_CERTIFICATE_SUBJECT, 1033 | "KEY_VALUE_LOCATION": KEY_VALUE_LOCATION, 1034 | "KEY_VALUE_LOCATION_VALUE": KEY_VALUE_LOCATION_VALUE, 1035 | "KEY_VALUE_LOCATION_TYPE": KEY_VALUE_LOCATION_TYPE, 1036 | "KEY_VALUE_PRESENT": KEY_VALUE_PRESENT, 1037 | "ORIGINAL_CREATION_DATE": ORIGINAL_CREATION_DATE, 1038 | "PGP_KEY": PGP_KEY, 1039 | "PGP_KEY_VERSION": PGP_KEY_VERSION, 1040 | "ALTERNATIVE_NAME": ALTERNATIVE_NAME, 1041 | "ALTERNATIVE_NAME_VALUE": ALTERNATIVE_NAME_VALUE, 1042 | "ALTERNATIVE_NAME_TYPE": ALTERNATIVE_NAME_TYPE, 1043 | "DATA": DATA, 1044 | "SIGNATURE_DATA": SIGNATURE_DATA, 1045 | "DATA_LENGTH": DATA_LENGTH, 1046 | "RANDOM_IV": RANDOM_IV, 1047 | "MAC_DATA": MAC_DATA, 1048 | "ATTESTATION_TYPE": ATTESTATION_TYPE, 1049 | "NONCE": NONCE, 1050 | "NONCE_ID": NONCE_ID, 1051 | "NONCE_VALUE": NONCE_VALUE, 1052 | "ATTESTATION_MEASUREMENT": ATTESTATION_MEASUREMENT, 1053 | "ATTESTATION_ASSERTION": ATTESTATION_ASSERTION, 1054 | "IV_LENGTH": IV_LENGTH, 1055 | "TAG_LENGTH": TAG_LENGTH, 1056 | "FIXED_FIELD_LENGTH": FIXED_FIELD_LENGTH, 1057 | "COUNTER_LENGTH": COUNTER_LENGTH, 1058 | "INITIAL_COUNTER_VALUE": INITIAL_COUNTER_VALUE, 1059 | "INVOCATION_FIELD_LENGTH": INVOCATION_FIELD_LENGTH, 1060 | "ATTESTATION_CAPABLE_INDICATOR": ATTESTATION_CAPABLE_INDICATOR, 1061 | "OFFSET_ITEMS": OFFSET_ITEMS, 1062 | "LOCATED_ITEMS": LOCATED_ITEMS, 1063 | "CORRELATION_VALUE": CORRELATION_VALUE, 1064 | "INIT_INDICATOR": INIT_INDICATOR, 1065 | "FINAL_INDICATOR": FINAL_INDICATOR, 1066 | "RNG_PARAMETERS": RNG_PARAMETERS, 1067 | "RNG_ALGORITHM": RNG_ALGORITHM, 1068 | "DRBG_ALGORITHM": DRBG_ALGORITHM, 1069 | "FIPS186_VARIATION": FIPS186_VARIATION, 1070 | "PREDICTION_RESISTANCE": PREDICTION_RESISTANCE, 1071 | "RANDOM_NUMBER_GENERATOR": RANDOM_NUMBER_GENERATOR, 1072 | "VALIDATION_INFORMATION": VALIDATION_INFORMATION, 1073 | "VALIDATION_AUTHORITY_TYPE": VALIDATION_AUTHORITY_TYPE, 1074 | "VALIDATION_AUTHORITY_COUNTRY": VALIDATION_AUTHORITY_COUNTRY, 1075 | "VALIDATION_AUTHORITY_URI": VALIDATION_AUTHORITY_URI, 1076 | "VALIDATION_VERSION_MAJOR": VALIDATION_VERSION_MAJOR, 1077 | "VALIDATION_VERSION_MINOR": VALIDATION_VERSION_MINOR, 1078 | "VALIDATION_TYPE": VALIDATION_TYPE, 1079 | "VALIDATION_LEVEL": VALIDATION_LEVEL, 1080 | "VALIDATION_CERTIFICATE_IDENTIFIER": VALIDATION_CERTIFICATE_IDENTIFIER, 1081 | "VALIDATION_CERTIFICATE_URI": VALIDATION_CERTIFICATE_URI, 1082 | "VALIDATION_VENDOR_URI": VALIDATION_VENDOR_URI, 1083 | "VALIDATION_PROFILE": VALIDATION_PROFILE, 1084 | "PROFILE_INFORMATION": PROFILE_INFORMATION, 1085 | "PROFILE_NAME": PROFILE_NAME, 1086 | "SERVER_URI": SERVER_URI, 1087 | "SERVER_PORT": SERVER_PORT, 1088 | "STREAMING_CAPABILITY": STREAMING_CAPABILITY, 1089 | "ASYNCHRONOUS_CAPABILITY": ASYNCHRONOUS_CAPABILITY, 1090 | "ATTESTATION_CAPABILITY": ATTESTATION_CAPABILITY, 1091 | "UNWRAP_MODE": UNWRAP_MODE, 1092 | "DESTROY_ACTION": DESTROY_ACTION, 1093 | "SHREDDING_ALGORITHM": SHREDDING_ALGORITHM, 1094 | "RNG_MODE": RNG_MODE, 1095 | "CLIENT_REGISTRATION_METHOD": CLIENT_REGISTRATION_METHOD, 1096 | "CAPABILITY_INFORMATION": CAPABILITY_INFORMATION, 1097 | "KEY_WRAP_TYPE": KEY_WRAP_TYPE, 1098 | "BATCH_UNDO_CAPABILITY": BATCH_UNDO_CAPABILITY, 1099 | "BATCH_CONTINUE_CAPABILITY": BATCH_CONTINUE_CAPABILITY, 1100 | "PKCS12_FRIENDLY_NAME": PKCS12_FRIENDLY_NAME, 1101 | "DESCRIPTION": DESCRIPTION, 1102 | "COMMENT": COMMENT, 1103 | "AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA": AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA, 1104 | "AUTHENTICATED_ENCRYPTION_TAG": AUTHENTICATED_ENCRYPTION_TAG, 1105 | "SALT_LENGTH": SALT_LENGTH, 1106 | "MASK_GENERATOR": MASK_GENERATOR, 1107 | "MASK_GENERATOR_HASHING_ALGORITHM": MASK_GENERATOR_HASHING_ALGORITHM, 1108 | "P_SOURCE": P_SOURCE, 1109 | "TRAILER_FIELD": TRAILER_FIELD, 1110 | "CLIENT_CORRELATION_VALUE": CLIENT_CORRELATION_VALUE, 1111 | "SERVER_CORRELATION_VALUE": SERVER_CORRELATION_VALUE, 1112 | "DIGESTED_DATA": DIGESTED_DATA, 1113 | "CERTIFICATE_SUBJECT_CN": CERTIFICATE_SUBJECT_CN, 1114 | "CERTIFICATE_SUBJECT_O": CERTIFICATE_SUBJECT_O, 1115 | "CERTIFICATE_SUBJECT_OU": CERTIFICATE_SUBJECT_OU, 1116 | "CERTIFICATE_SUBJECT_EMAIL": CERTIFICATE_SUBJECT_EMAIL, 1117 | "CERTIFICATE_SUBJECT_C": CERTIFICATE_SUBJECT_C, 1118 | "CERTIFICATE_SUBJECT_ST": CERTIFICATE_SUBJECT_ST, 1119 | "CERTIFICATE_SUBJECT_L": CERTIFICATE_SUBJECT_L, 1120 | "CERTIFICATE_SUBJECT_UID": CERTIFICATE_SUBJECT_UID, 1121 | "CERTIFICATE_SUBJECT_SERIAL_NUMBER": CERTIFICATE_SUBJECT_SERIAL_NUMBER, 1122 | "CERTIFICATE_SUBJECT_TITLE": CERTIFICATE_SUBJECT_TITLE, 1123 | "CERTIFICATE_SUBJECT_DC": CERTIFICATE_SUBJECT_DC, 1124 | "CERTIFICATE_SUBJECT_DN_QUALIFIER": CERTIFICATE_SUBJECT_DN_QUALIFIER, 1125 | "CERTIFICATE_ISSUER_CN": CERTIFICATE_ISSUER_CN, 1126 | "CERTIFICATE_ISSUER_O": CERTIFICATE_ISSUER_O, 1127 | "CERTIFICATE_ISSUER_OU": CERTIFICATE_ISSUER_OU, 1128 | "CERTIFICATE_ISSUER_EMAIL": CERTIFICATE_ISSUER_EMAIL, 1129 | "CERTIFICATE_ISSUER_C": CERTIFICATE_ISSUER_C, 1130 | "CERTIFICATE_ISSUER_ST": CERTIFICATE_ISSUER_ST, 1131 | "CERTIFICATE_ISSUER_L": CERTIFICATE_ISSUER_L, 1132 | "CERTIFICATE_ISSUER_UID": CERTIFICATE_ISSUER_UID, 1133 | "CERTIFICATE_ISSUER_SERIAL_NUMBER": CERTIFICATE_ISSUER_SERIAL_NUMBER, 1134 | "CERTIFICATE_ISSUER_TITLE": CERTIFICATE_ISSUER_TITLE, 1135 | "CERTIFICATE_ISSUER_DC": CERTIFICATE_ISSUER_DC, 1136 | "CERTIFICATE_ISSUER_DN_QUALIFIER": CERTIFICATE_ISSUER_DN_QUALIFIER, 1137 | "SENSITIVE": SENSITIVE, 1138 | "ALWAYS_SENSITIVE": ALWAYS_SENSITIVE, 1139 | "EXTRACTABLE": EXTRACTABLE, 1140 | "NEVER_EXTRACTABLE": NEVER_EXTRACTABLE, 1141 | "REPLACE_EXISTING": REPLACE_EXISTING, 1142 | "ATTRIBUTES": ATTRIBUTES, 1143 | "COMMON_ATTRIBUTES": COMMON_ATTRIBUTES, 1144 | "PRIVATE_KEY_ATTRIBUTES": PRIVATE_KEY_ATTRIBUTES, 1145 | "PUBLIC_KEY_ATTRIBUTES": PUBLIC_KEY_ATTRIBUTES, 1146 | "EXTENSION_ENUMERATION": EXTENSION_ENUMERATION, 1147 | "EXTENSION_ATTRIBUTE": EXTENSION_ATTRIBUTE, 1148 | "EXTENSION_PARENT_STRUCTURE_TAG": EXTENSION_PARENT_STRUCTURE_TAG, 1149 | "EXTENSION_DESCRIPTION": EXTENSION_DESCRIPTION, 1150 | "SERVER_NAME": SERVER_NAME, 1151 | "SERVER_SERIAL_NUMBER": SERVER_SERIAL_NUMBER, 1152 | "SERVER_VERSION": SERVER_VERSION, 1153 | "SERVER_LOAD": SERVER_LOAD, 1154 | "PRODUCT_NAME": PRODUCT_NAME, 1155 | "BUILD_LEVEL": BUILD_LEVEL, 1156 | "BUILD_DATE": BUILD_DATE, 1157 | "CLUSTER_INFO": CLUSTER_INFO, 1158 | "ALTERNATE_FAILOVER_ENDPOINTS": ALTERNATE_FAILOVER_ENDPOINTS, 1159 | "SHORT_UNIQUE_IDENTIFIER": SHORT_UNIQUE_IDENTIFIER, 1160 | "RESERVED": RESERVED, 1161 | "TAG": TAG, 1162 | "CERTIFICATE_REQUEST_UNIQUE_IDENTIFIER": CERTIFICATE_REQUEST_UNIQUE_IDENTIFIER, 1163 | "NIST_KEY_TYPE": NIST_KEY_TYPE, 1164 | "ATTRIBUTE_REFERENCE": ATTRIBUTE_REFERENCE, 1165 | "CURRENT_ATTRIBUTE": CURRENT_ATTRIBUTE, 1166 | "NEW_ATTRIBUTE": NEW_ATTRIBUTE, 1167 | "CERTIFICATE_REQUEST_VALUE": CERTIFICATE_REQUEST_VALUE, 1168 | "LOG_MESSAGE": LOG_MESSAGE, 1169 | "PROFILE_VERSION": PROFILE_VERSION, 1170 | "PROFILE_VERSION_MAJOR": PROFILE_VERSION_MAJOR, 1171 | "PROFILE_VERSION_MINOR": PROFILE_VERSION_MINOR, 1172 | "PROTECTION_LEVEL": PROTECTION_LEVEL, 1173 | "PROTECTION_PERIOD": PROTECTION_PERIOD, 1174 | "QUANTUM_SAFE": QUANTUM_SAFE, 1175 | "QUANTUM_SAFE_CAPABILITY": QUANTUM_SAFE_CAPABILITY, 1176 | "TICKET": TICKET, 1177 | "TICKET_TYPE": TICKET_TYPE, 1178 | "TICKET_VALUE": TICKET_VALUE, 1179 | "REQUEST_COUNT": REQUEST_COUNT, 1180 | "RIGHTS": RIGHTS, 1181 | "OBJECTS": OBJECTS, 1182 | "OPERATIONS": OPERATIONS, 1183 | "RIGHT": RIGHT, 1184 | "ENDPOINT_ROLE": ENDPOINT_ROLE, 1185 | "DEFAULTS_INFORMATION": DEFAULTS_INFORMATION, 1186 | "OBJECT_DEFAULTS": OBJECT_DEFAULTS, 1187 | "EPHEMERAL": EPHEMERAL, 1188 | "SERVER_HASHED_PASSWORD": SERVER_HASHED_PASSWORD, 1189 | "ONE_TIME_PASSWORD": ONE_TIME_PASSWORD, 1190 | "HASHED_PASSWORD": HASHED_PASSWORD, 1191 | "ADJUSTMENT_TYPE": ADJUSTMENT_TYPE, 1192 | "PKCS11_INTERFACE": PKCS11_INTERFACE, 1193 | "PKCS11_FUNCTION": PKCS11_FUNCTION, 1194 | "PKCS11_INPUT_PARAMETERS": PKCS11_INPUT_PARAMETERS, 1195 | "PKCS11_OUTPUT_PARAMETERS": PKCS11_OUTPUT_PARAMETERS, 1196 | "PKCS11_RETURN_CODE": PKCS11_RETURN_CODE, 1197 | "PROTECTION_STORAGE_MASK": PROTECTION_STORAGE_MASK, 1198 | "PROTECTION_STORAGE_MASKS": PROTECTION_STORAGE_MASKS, 1199 | "INTEROP_FUNCTION": INTEROP_FUNCTION, 1200 | "INTEROP_IDENTIFIER": INTEROP_IDENTIFIER, 1201 | "ADJUSTMENT_VALUE": ADJUSTMENT_VALUE, 1202 | } 1203 | 1204 | var operationMap = map[Enum]string{ 1205 | OPERATION_CREATE: "OPERATION_CREATE", 1206 | OPERATION_CREATE_KEY_PAIR: "OPERATION_CREATE_KEY_PAIR", 1207 | OPERATION_REGISTER: "OPERATION_REGISTER", 1208 | OPERATION_REKEY: "OPERATION_REKEY", 1209 | OPERATION_DERIVE_KEY: "OPERATION_DERIVE_KEY", 1210 | OPERATION_CERTIFY: "OPERATION_CERTIFY", 1211 | OPERATION_RECERTIFY: "OPERATION_RECERTIFY", 1212 | OPERATION_LOCATE: "OPERATION_LOCATE", 1213 | OPERATION_CHECK: "OPERATION_CHECK", 1214 | OPERATION_GET: "OPERATION_GET", 1215 | OPERATION_GET_ATTRIBUTES: "OPERATION_GET_ATTRIBUTES", 1216 | OPERATION_GET_ATTRIBUTE_LIST: "OPERATION_GET_ATTRIBUTE_LIST", 1217 | OPERATION_ADD_ATTRIBUTE: "OPERATION_ADD_ATTRIBUTE", 1218 | OPERATION_MODIFY_ATTRIBUTE: "OPERATION_MODIFY_ATTRIBUTE", 1219 | OPERATION_DELETE_ATTRIBUTE: "OPERATION_DELETE_ATTRIBUTE", 1220 | OPERATION_OBTAIN_LEASE: "OPERATION_OBTAIN_LEASE", 1221 | OPERATION_GET_USAGE_ALLOCATION: "OPERATION_GET_USAGE_ALLOCATION", 1222 | OPERATION_ACTIVATE: "OPERATION_ACTIVATE", 1223 | OPERATION_REVOKE: "OPERATION_REVOKE", 1224 | OPERATION_DESTROY: "OPERATION_DESTROY", 1225 | OPERATION_ARCHIVE: "OPERATION_ARCHIVE", 1226 | OPERATION_RECOVER: "OPERATION_RECOVER", 1227 | OPERATION_VALIDATE: "OPERATION_VALIDATE", 1228 | OPERATION_QUERY: "OPERATION_QUERY", 1229 | OPERATION_CANCEL: "OPERATION_CANCEL", 1230 | OPERATION_POLL: "OPERATION_POLL", 1231 | OPERATION_NOTIFY: "OPERATION_NOTIFY", 1232 | OPERATION_PUT: "OPERATION_PUT", 1233 | OPERATION_REKEY_KEY_PAIR: "OPERATION_REKEY_KEY_PAIR", 1234 | OPERATION_DISCOVER_VERSIONS: "OPERATION_DISCOVER_VERSIONS", 1235 | OPERATION_ENCRYPT: "OPERATION_ENCRYPT", 1236 | OPERATION_DECRYPT: "OPERATION_DECRYPT", 1237 | OPERATION_SIGN: "OPERATION_SIGN", 1238 | OPERATION_SIGNATURE_VERIFY: "OPERATION_SIGNATURE_VERIFY", 1239 | OPERATION_MAC: "OPERATION_MAC", 1240 | OPERATION_MAC_VERIFY: "OPERATION_MAC_VERIFY", 1241 | OPERATION_RNG_RETRIEVE: "OPERATION_RNG_RETRIEVE", 1242 | OPERATION_RNG_SEED: "OPERATION_RNG_SEED", 1243 | OPERATION_HASH: "OPERATION_HASH", 1244 | OPERATION_CREATE_SPLIT_KEY: "OPERATION_CREATE_SPLIT_KEY", 1245 | OPERATION_JOIN_SPLIT_KEY: "OPERATION_JOIN_SPLIT_KEY", 1246 | OPERATION_IMPORT: "OPERATION_IMPORT", 1247 | OPERATION_EXPORT: "OPERATION_EXPORT", 1248 | OPERATION_LOG: "OPERATION_LOG", 1249 | OPERATION_LOGIN: "OPERATION_LOGIN", 1250 | OPERATION_LOGOUT: "OPERATION_LOGOUT", 1251 | OPERATION_DELEGATED_LOGIN: "OPERATION_DELEGATED_LOGIN", 1252 | OPERATION_ADJUST_ATTRIBUTE: "OPERATION_ADJUST_ATTRIBUTE", 1253 | OPERATION_SET_ATTRIBUTE: "OPERATION_SET_ATTRIBUTE", 1254 | OPERATION_SET_ENDPOINT_ROLE: "OPERATION_SET_ENDPOINT_ROLE", 1255 | OPERATION_PKCS_11: "OPERATION_PKCS_11", 1256 | OPERATION_INTEROP: "OPERATION_INTEROP", 1257 | OPERATION_REPROVISION: "OPERATION_REPROVISION", 1258 | } 1259 | -------------------------------------------------------------------------------- /decode.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "bufio" 9 | "encoding/binary" 10 | "io" 11 | "io/ioutil" 12 | "reflect" 13 | 14 | "github.com/pkg/errors" 15 | ) 16 | 17 | // Decoder implements KMIP protocol decoding 18 | // 19 | // Decoding works exactly the same way as encoding 20 | // (see Encoder documentation), but the other way around. 21 | type Decoder struct { 22 | r io.Reader 23 | s io.ByteScanner 24 | 25 | lastTag Tag 26 | } 27 | 28 | // NewDecoder builds Decoder which reads from r 29 | // 30 | // Buffering can be disabled by providing reader 31 | // which implements io.ByteScanner 32 | func NewDecoder(r io.Reader) *Decoder { 33 | d := &Decoder{ 34 | r: r, 35 | } 36 | 37 | if s, ok := r.(io.ByteScanner); ok { 38 | d.s = s 39 | } else { 40 | br := bufio.NewReader(r) 41 | d.r = br 42 | d.s = br 43 | } 44 | 45 | return d 46 | } 47 | 48 | func (d *Decoder) internalReadTag() (t Tag, err error) { 49 | var b [3]byte 50 | 51 | _, err = io.ReadFull(d.r, b[:]) 52 | if err != nil { 53 | return 54 | } 55 | 56 | t = Tag(binary.BigEndian.Uint32(append([]byte{0}, b[:]...))) 57 | 58 | return 59 | } 60 | 61 | func (d *Decoder) readTag() (t Tag, err error) { 62 | if d.lastTag != 0 { 63 | t, d.lastTag = d.lastTag, 0 64 | return 65 | } 66 | 67 | t, err = d.internalReadTag() 68 | return 69 | } 70 | 71 | func (d *Decoder) peekTag() (t Tag, err error) { 72 | if d.lastTag != 0 { 73 | return d.lastTag, nil 74 | } 75 | 76 | d.lastTag, err = d.internalReadTag() 77 | t = d.lastTag 78 | 79 | return 80 | } 81 | 82 | func (d *Decoder) expectTag(expected Tag) error { 83 | t, err := d.readTag() 84 | if err != nil { 85 | return err 86 | } 87 | 88 | if expected != t && expected != ANY_TAG { 89 | return errors.Errorf("expecting tag %x, but %x was encountered", expected, t) 90 | } 91 | 92 | return nil 93 | } 94 | 95 | func (d *Decoder) readType() (t Type, err error) { 96 | var b byte 97 | 98 | b, err = d.s.ReadByte() 99 | t = Type(b) 100 | 101 | return 102 | } 103 | 104 | func (d *Decoder) expectType(expected Type) error { 105 | t, err := d.readType() 106 | if err != nil { 107 | return err 108 | } 109 | 110 | if expected != t { 111 | return errors.Errorf("expecting type %d, but %d was encountered", expected, t) 112 | } 113 | 114 | return nil 115 | } 116 | 117 | func (d *Decoder) readLength() (l uint32, err error) { 118 | var b [4]byte 119 | 120 | _, err = io.ReadFull(d.r, b[:]) 121 | if err != nil { 122 | return 123 | } 124 | 125 | l = binary.BigEndian.Uint32(b[:]) 126 | 127 | return 128 | } 129 | 130 | func (d *Decoder) expectLength(expected uint32) error { 131 | l, err := d.readLength() 132 | if err != nil { 133 | return err 134 | } 135 | 136 | if expected != l { 137 | return errors.Errorf("expecting length %d, but %d was encountered", expected, l) 138 | } 139 | 140 | return nil 141 | } 142 | 143 | // Decode structure from the reader into v 144 | func (d *Decoder) Decode(v interface{}) error { 145 | rv := reflect.ValueOf(v) 146 | if !rv.IsValid() { 147 | return errors.New("invalid value") 148 | } 149 | if rv.Kind() == reflect.Ptr { 150 | rv = rv.Elem() 151 | } 152 | if !rv.IsValid() { 153 | return errors.New("invalid pointer value") 154 | } 155 | if !rv.CanSet() { 156 | return errors.New("unsettable value") 157 | } 158 | 159 | structDesc, err := getStructDesc(rv.Type()) 160 | if err != nil { 161 | return err 162 | } 163 | 164 | _, err = d.decode(rv, structDesc) 165 | return err 166 | } 167 | 168 | func (d *Decoder) decodeValue(f field, t reflect.Type, ff reflect.Value) (n int, v interface{}, err error) { 169 | if f.skip { 170 | if err = d.expectTag(f.tag); err != nil { 171 | return 172 | } 173 | 174 | if _, err = d.readType(); err != nil { 175 | return 176 | } 177 | 178 | var l uint32 179 | if l, err = d.readLength(); err != nil { 180 | return 181 | } 182 | 183 | n = 8 184 | 185 | if l%8 != 0 { 186 | l += 8 - l%8 187 | } 188 | 189 | _, err = io.CopyN(ioutil.Discard, d.r, int64(l)) 190 | n += int(l) 191 | 192 | return 193 | } 194 | 195 | switch f.typ { 196 | case INTEGER: 197 | v, err = d.readInteger(f.tag) 198 | n = 16 199 | case LONG_INTEGER: 200 | v, err = d.readLongInteger(f.tag) 201 | n = 16 202 | case ENUMERATION: 203 | v, err = d.readEnum(f.tag) 204 | n = 16 205 | case BOOLEAN: 206 | v, err = d.readBool(f.tag) 207 | n = 16 208 | case DATE_TIME: 209 | v, err = d.readTime(f.tag) 210 | n = 16 211 | case INTERVAL: 212 | v, err = d.readDuration(f.tag) 213 | n = 16 214 | case BYTE_STRING: 215 | n, v, err = d.readBytes(f.tag) 216 | case TEXT_STRING: 217 | n, v, err = d.readString(f.tag) 218 | case STRUCTURE: 219 | var ( 220 | sD *structDesc 221 | vv reflect.Value 222 | ) 223 | 224 | if f.dynamic { 225 | dD, ok := ff.Addr().Interface().(DynamicDispatch) 226 | if !ok { 227 | err = errors.New("field is dynamic, but DynamicDispatch is not implemented") 228 | return 229 | } 230 | 231 | var val interface{} 232 | 233 | val, err = dD.BuildFieldValue(f.name) 234 | if err != nil { 235 | return 236 | } 237 | 238 | vv = reflect.ValueOf(val) 239 | 240 | switch vv.Type() { 241 | case typeOfInt32: 242 | f.typ = INTEGER 243 | return d.decodeValue(f, t, ff) 244 | case typeOfInt64: 245 | f.typ = LONG_INTEGER 246 | return d.decodeValue(f, t, ff) 247 | case typeOfEnum: 248 | f.typ = ENUMERATION 249 | return d.decodeValue(f, t, ff) 250 | case typeOfBool: 251 | f.typ = BOOLEAN 252 | return d.decodeValue(f, t, ff) 253 | case typeOfBytes: 254 | f.typ = BYTE_STRING 255 | return d.decodeValue(f, t, ff) 256 | case typeOfString: 257 | f.typ = TEXT_STRING 258 | return d.decodeValue(f, t, ff) 259 | case typeOfTime: 260 | f.typ = DATE_TIME 261 | return d.decodeValue(f, t, ff) 262 | } 263 | 264 | sD, err = getStructDesc(vv.Type().Elem()) 265 | if err != nil { 266 | return 267 | } 268 | } else { 269 | 270 | sD, err = getStructDesc(t) 271 | if err != nil { 272 | return 273 | } 274 | 275 | vv = reflect.New(t) 276 | } 277 | 278 | sD.tag = f.tag 279 | n, err = d.decode(vv, sD) 280 | 281 | v = vv.Elem().Interface() 282 | default: 283 | panic("unsupported type") 284 | } 285 | 286 | return 287 | } 288 | 289 | func (d *Decoder) decode(rv reflect.Value, structD *structDesc) (n int, err error) { 290 | if rv.Kind() == reflect.Ptr { 291 | rv = rv.Elem() 292 | } 293 | 294 | if err = d.expectTag(structD.tag); err != nil { 295 | return 296 | } 297 | 298 | if err = d.expectType(STRUCTURE); err != nil { 299 | return 300 | } 301 | 302 | n += 4 303 | 304 | var expectedLen, actualLen uint32 305 | if expectedLen, err = d.readLength(); err != nil { 306 | return 307 | } 308 | 309 | n += 4 310 | 311 | // initialize wrapped decoder with limited reader 312 | dd := NewDecoder(io.LimitReader(d.r, int64(expectedLen))) 313 | 314 | for _, f := range structD.fields { 315 | var tag Tag 316 | tag, err = dd.peekTag() 317 | 318 | if err == io.EOF && !f.required { 319 | err = nil 320 | continue 321 | } 322 | 323 | if err != nil { 324 | err = errors.Wrapf(err, "error reading field %v", f.name) 325 | return 326 | } 327 | 328 | if !f.required && tag != f.tag && f.tag != ANY_TAG { 329 | continue 330 | } 331 | 332 | var ( 333 | nn int 334 | v interface{} 335 | ) 336 | 337 | ff := rv.FieldByIndex(f.idx) 338 | 339 | if f.sliceof { 340 | ff.Set(reflect.MakeSlice(ff.Type(), 0, 0)) 341 | 342 | for { 343 | nn, v, err = dd.decodeValue(f, ff.Type().Elem(), rv) 344 | if err != nil { 345 | err = errors.Wrapf(err, "error reading field %v", f.name) 346 | return 347 | } 348 | 349 | n += nn 350 | actualLen += uint32(nn) 351 | 352 | if !f.skip { 353 | ff.Set(reflect.Append(ff, reflect.ValueOf(v))) 354 | } 355 | 356 | if actualLen >= expectedLen { 357 | break 358 | } 359 | 360 | tag, err = dd.peekTag() 361 | if err != nil { 362 | return 363 | } 364 | 365 | if tag != f.tag { 366 | break 367 | } 368 | } 369 | } else { 370 | nn, v, err = dd.decodeValue(f, ff.Type(), rv) 371 | if err != nil { 372 | err = errors.Wrapf(err, "error reading field %v", f.name) 373 | return 374 | } 375 | 376 | n += nn 377 | actualLen += uint32(nn) 378 | 379 | if !f.skip { 380 | ff.Set(reflect.ValueOf(v)) 381 | } 382 | } 383 | } 384 | 385 | if actualLen != expectedLen { 386 | err = errors.Errorf("error reading structure expected %d != actual %d", expectedLen, actualLen) 387 | } 388 | 389 | return 390 | } 391 | -------------------------------------------------------------------------------- /decode_core.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "encoding/binary" 9 | "io" 10 | "time" 11 | 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | func (d *Decoder) readInteger(expectedTag Tag) (v int32, err error) { 16 | if err = d.expectTag(expectedTag); err != nil { 17 | return 18 | } 19 | 20 | if err = d.expectType(INTEGER); err != nil { 21 | return 22 | } 23 | 24 | if err = d.expectLength(4); err != nil { 25 | return 26 | } 27 | 28 | var b [8]byte 29 | 30 | _, err = io.ReadFull(d.r, b[:]) 31 | if err != nil { 32 | return 33 | } 34 | 35 | v = int32(binary.BigEndian.Uint32(b[:4])) 36 | 37 | return 38 | } 39 | 40 | func (d *Decoder) readLongInteger(expectedTag Tag) (v int64, err error) { 41 | if err = d.expectTag(expectedTag); err != nil { 42 | return 43 | } 44 | 45 | if err = d.expectType(LONG_INTEGER); err != nil { 46 | return 47 | } 48 | 49 | if err = d.expectLength(8); err != nil { 50 | return 51 | } 52 | 53 | var b [8]byte 54 | 55 | _, err = io.ReadFull(d.r, b[:]) 56 | if err != nil { 57 | return 58 | } 59 | 60 | v = int64(binary.BigEndian.Uint64(b[:])) 61 | 62 | return 63 | } 64 | 65 | func (d *Decoder) readEnum(expectedTag Tag) (v Enum, err error) { 66 | if err = d.expectTag(expectedTag); err != nil { 67 | return 68 | } 69 | 70 | if err = d.expectType(ENUMERATION); err != nil { 71 | return 72 | } 73 | 74 | if err = d.expectLength(4); err != nil { 75 | return 76 | } 77 | 78 | var b [8]byte 79 | 80 | _, err = io.ReadFull(d.r, b[:]) 81 | if err != nil { 82 | return 83 | } 84 | 85 | v = Enum(binary.BigEndian.Uint32(b[:4])) 86 | 87 | return 88 | } 89 | 90 | func (d *Decoder) readBool(expectedTag Tag) (v bool, err error) { 91 | if err = d.expectTag(expectedTag); err != nil { 92 | return 93 | } 94 | 95 | if err = d.expectType(BOOLEAN); err != nil { 96 | return 97 | } 98 | 99 | if err = d.expectLength(8); err != nil { 100 | return 101 | } 102 | 103 | var b [8]byte 104 | 105 | _, err = io.ReadFull(d.r, b[:]) 106 | if err != nil { 107 | return 108 | } 109 | 110 | for i := 0; i < 7; i++ { 111 | if b[i] != 0 { 112 | err = errors.Errorf("unexpected boolean value: %v", b) 113 | return 114 | } 115 | } 116 | 117 | switch b[7] { 118 | case 1: 119 | v = true 120 | case 0: 121 | v = false 122 | default: 123 | err = errors.Errorf("unexpected boolean value: %v", b) 124 | } 125 | 126 | return 127 | } 128 | 129 | func (d *Decoder) readByteSlice(expectedTag Tag, expectedType Type) (n int, v []byte, err error) { 130 | if err = d.expectTag(expectedTag); err != nil { 131 | return 132 | } 133 | 134 | if err = d.expectType(expectedType); err != nil { 135 | return 136 | } 137 | 138 | var l uint32 139 | if l, err = d.readLength(); err != nil { 140 | return 141 | } 142 | 143 | v = make([]byte, l) 144 | _, err = io.ReadFull(d.r, v) 145 | if err != nil { 146 | return 147 | } 148 | 149 | n = int(l) + 8 150 | 151 | // padding 152 | var b [8]byte 153 | if l%8 != 0 { 154 | _, err = io.ReadFull(d.r, b[:8-l%8]) 155 | if err != nil { 156 | return 157 | } 158 | n += int(8 - l%8) 159 | } 160 | 161 | return 162 | } 163 | 164 | func (d *Decoder) readBytes(expectedTag Tag) (n int, v []byte, err error) { 165 | n, v, err = d.readByteSlice(expectedTag, BYTE_STRING) 166 | return 167 | } 168 | 169 | func (d *Decoder) readString(expectedTag Tag) (n int, v string, err error) { 170 | var b []byte 171 | n, b, err = d.readByteSlice(expectedTag, TEXT_STRING) 172 | v = string(b) 173 | return 174 | } 175 | 176 | func (d *Decoder) readTime(expectedTag Tag) (v time.Time, err error) { 177 | if err = d.expectTag(expectedTag); err != nil { 178 | return 179 | } 180 | 181 | if err = d.expectType(DATE_TIME); err != nil { 182 | return 183 | } 184 | 185 | if err = d.expectLength(8); err != nil { 186 | return 187 | } 188 | 189 | var b [8]byte 190 | 191 | _, err = io.ReadFull(d.r, b[:]) 192 | if err != nil { 193 | return 194 | } 195 | 196 | v = time.Unix(int64(binary.BigEndian.Uint64(b[:])), 0) 197 | 198 | return 199 | } 200 | 201 | func (d *Decoder) readDuration(expectedTag Tag) (v time.Duration, err error) { 202 | if err = d.expectTag(expectedTag); err != nil { 203 | return 204 | } 205 | 206 | if err = d.expectType(INTERVAL); err != nil { 207 | return 208 | } 209 | 210 | if err = d.expectLength(4); err != nil { 211 | return 212 | } 213 | 214 | var b [8]byte 215 | 216 | _, err = io.ReadFull(d.r, b[:]) 217 | if err != nil { 218 | return 219 | } 220 | 221 | v = time.Duration(binary.BigEndian.Uint32(b[:4])) * time.Second 222 | 223 | return 224 | } 225 | -------------------------------------------------------------------------------- /decode_test.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "bytes" 9 | "encoding/hex" 10 | "strings" 11 | "testing" 12 | "time" 13 | 14 | "github.com/stretchr/testify/suite" 15 | ) 16 | 17 | type DecoderSuite struct { 18 | suite.Suite 19 | } 20 | 21 | func (s *DecoderSuite) parseSpecValue(val string) []byte { 22 | val = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(val, "_", ""), "|", ""), " ", "") 23 | 24 | res, err := hex.DecodeString(val) 25 | s.Require().NoError(err) 26 | 27 | return res 28 | } 29 | 30 | func (s *DecoderSuite) TestReadInteger() { 31 | v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 02 | 00 00 00 04 | 00 00 00 08 00 00 00 00"))).readInteger(COMPROMISE_DATE) 32 | s.Assert().NoError(err) 33 | s.Assert().EqualValues(8, v) 34 | 35 | // padding missing 36 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 02 | 00 00 00 04 | 00 00 00 08 00 00 00 "))).readInteger(COMPROMISE_DATE) 37 | s.Assert().EqualError(err, "unexpected EOF") 38 | 39 | // no value 40 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 02 | 00 00 00 04 | 00"))).readInteger(COMPROMISE_DATE) 41 | s.Assert().EqualError(err, "unexpected EOF") 42 | 43 | // no length 44 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 02 | 00 00 "))).readInteger(COMPROMISE_DATE) 45 | s.Assert().EqualError(err, "unexpected EOF") 46 | 47 | // no type 48 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | "))).readInteger(COMPROMISE_DATE) 49 | s.Assert().EqualError(err, "EOF") 50 | 51 | // no tag 52 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42"))).readInteger(COMPROMISE_DATE) 53 | s.Assert().EqualError(err, "unexpected EOF") 54 | 55 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 21 | 02 | 00 00 00 04 | 00 00 00 08 00 00 00 "))).readInteger(CRYPTOGRAPHIC_ALGORITHM) 56 | s.Assert().EqualError(err, "expecting tag 420028, but 420021 was encountered") 57 | 58 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 01 | 00 00 00 04 | 00 00 00 08 00 00 00 00"))).readInteger(COMPROMISE_DATE) 59 | s.Assert().EqualError(err, "expecting type 2, but 1 was encountered") 60 | 61 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 02 | 00 00 00 03 | 00 00 00 08 00 00 00 00"))).readInteger(COMPROMISE_DATE) 62 | s.Assert().EqualError(err, "expecting length 4, but 3 was encountered") 63 | } 64 | 65 | func (s *DecoderSuite) TestReadLongInteger() { 66 | v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 03 | 00 00 00 08 | 01 B6 9B 4B A5 74 92 00"))).readLongInteger(COMPROMISE_DATE) 67 | s.Assert().NoError(err) 68 | s.Assert().EqualValues(123456789000000000, v) 69 | } 70 | 71 | func (s *DecoderSuite) TestReadEnum() { 72 | v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 05 | 00 00 00 04 | 00 00 00 FF 00 00 00 00"))).readEnum(COMPROMISE_DATE) 73 | s.Assert().NoError(err) 74 | s.Assert().EqualValues(255, v) 75 | } 76 | 77 | func (s *DecoderSuite) TestReadBool() { 78 | v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 00 00 00 01"))).readBool(COMPROMISE_DATE) 79 | s.Assert().NoError(err) 80 | s.Assert().True(v) 81 | 82 | v, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 00 00 00 00"))).readBool(COMPROMISE_DATE) 83 | s.Assert().NoError(err) 84 | s.Assert().False(v) 85 | 86 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 00 00 00 03"))).readBool(COMPROMISE_DATE) 87 | s.Assert().EqualError(err, "unexpected boolean value: [0 0 0 0 0 0 0 3]") 88 | 89 | _, err = NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 01 00 00 00"))).readBool(COMPROMISE_DATE) 90 | s.Assert().EqualError(err, "unexpected boolean value: [0 0 0 0 1 0 0 0]") 91 | } 92 | 93 | func (s *DecoderSuite) TestReadString() { 94 | n, v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 07 | 00 00 00 0B | 48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 00"))).readString(COMPROMISE_DATE) 95 | s.Assert().NoError(err) 96 | s.Assert().EqualValues("Hello World", v) 97 | s.Assert().EqualValues(24, n) 98 | } 99 | 100 | func (s *DecoderSuite) TestReadBytes() { 101 | n, v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 08 | 00 00 00 03 | 01 02 03 00 00 00 00 00"))).readBytes(COMPROMISE_DATE) 102 | s.Assert().NoError(err) 103 | s.Assert().EqualValues([]byte{1, 2, 3}, v) 104 | s.Assert().EqualValues(16, n) 105 | } 106 | 107 | func (s *DecoderSuite) TestReadTime() { 108 | v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 09 | 00 00 00 08 | 00 00 00 00 47 DA 67 F8"))).readTime(COMPROMISE_DATE) 109 | s.Assert().NoError(err) 110 | s.Assert().Equal("2008-03-14T11:56:40Z", v.UTC().Format(time.RFC3339)) 111 | } 112 | 113 | func (s *DecoderSuite) TestReadDuration() { 114 | v, err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 0A | 00 00 00 04 | 00 0D 2F 00 00 00 00 00"))).readDuration(COMPROMISE_DATE) 115 | s.Assert().NoError(err) 116 | s.Assert().Equal(10*24*time.Hour, v) 117 | } 118 | 119 | func (s *DecoderSuite) TestDecodeStruct() { 120 | type tt struct { 121 | Tag `kmip:"COMPROMISE_DATE"` 122 | Other string 123 | A Enum `kmip:"APPLICATION_SPECIFIC_INFORMATION,required"` 124 | B int32 `kmip:"ARCHIVE_DATE,required"` 125 | C string `kmip:"COMPROMISE_DATE"` 126 | D []byte `kmip:"ACTIVATION_DATE"` 127 | } 128 | 129 | var v tt 130 | 131 | err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 01 | 00 00 00 20 | 42 00 04 | 05 | 00 00 00 04 | 00 00 00 FE 00 00 00 00 |" + 132 | " 42 00 05 | 02 | 00 00 00 04 | 00 00 00 FF 00 00 00 00"))).Decode(&v) 133 | s.Assert().NoError(err) 134 | 135 | s.Assert().EqualValues(254, v.A) 136 | s.Assert().EqualValues(255, v.B) 137 | } 138 | 139 | func (s *DecoderSuite) TestDecodeStructSkip() { 140 | type tt struct { 141 | Tag `kmip:"COMPROMISE_DATE"` 142 | Other string 143 | A Enum `kmip:"APPLICATION_SPECIFIC_INFORMATION,required"` 144 | B int32 `kmip:"ARCHIVE_DATE,skip"` 145 | } 146 | 147 | var v tt 148 | 149 | err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 01 | 00 00 00 20 | 42 00 04 | 05 | 00 00 00 04 | 00 00 00 FE 00 00 00 00 |" + 150 | " 42 00 05 | 02 | 00 00 00 04 | 00 00 00 FF 00 00 00 00"))).Decode(&v) 151 | s.Assert().NoError(err) 152 | 153 | s.Assert().EqualValues(254, v.A) 154 | s.Assert().EqualValues(0, v.B) 155 | } 156 | 157 | func (s *DecoderSuite) TestDecodeStructSkipAny() { 158 | type tt struct { 159 | Tag `kmip:"COMPROMISE_DATE"` 160 | A Enum `kmip:"APPLICATION_SPECIFIC_INFORMATION"` 161 | B interface{} `kmip:"-,skip"` 162 | } 163 | 164 | var v tt 165 | 166 | err := NewDecoder(bytes.NewReader(s.parseSpecValue("42 00 20 | 01 | 00 00 00 20 | 42 00 04 | 05 | 00 00 00 04 | 00 00 00 FE 00 00 00 00 |" + 167 | " 42 00 05 | 02 | 00 00 00 04 | 00 00 00 FF 00 00 00 00"))).Decode(&v) 168 | s.Assert().NoError(err) 169 | 170 | s.Assert().EqualValues(254, v.A) 171 | s.Assert().EqualValues(nil, v.B) 172 | } 173 | 174 | func (s *DecoderSuite) TestDecodeMessageCreate() { 175 | var m Request 176 | 177 | err := NewDecoder(bytes.NewReader(messageCreate)).Decode(&m) 178 | s.Assert().NoError(err) 179 | s.Assert().Equal( 180 | Request{ 181 | Header: RequestHeader{ 182 | Version: ProtocolVersion{Major: 1, Minor: 1}, 183 | BatchCount: 1, 184 | }, 185 | BatchItems: []RequestBatchItem{ 186 | { 187 | Operation: OPERATION_CREATE, 188 | RequestPayload: CreateRequest{ 189 | ObjectType: OBJECT_TYPE_SYMMETRIC_KEY, 190 | TemplateAttribute: TemplateAttribute{ 191 | Attributes: []Attribute{ 192 | { 193 | Name: ATTRIBUTE_NAME_CRYPTOGRAPHIC_ALGORITHM, 194 | Value: CRYPTO_AES, 195 | }, 196 | { 197 | Name: ATTRIBUTE_NAME_CRYPTOGRAPHIC_LENGTH, 198 | Value: int32(128), 199 | }, 200 | { 201 | Name: ATTRIBUTE_NAME_CRYPTOGRAPHIC_USAGE_MASK, 202 | Value: int32(12), 203 | }, 204 | { 205 | Name: ATTRIBUTE_NAME_INITIAL_DATE, 206 | Value: time.Unix(12345, 0), 207 | }, 208 | }, 209 | }, 210 | }, 211 | }, 212 | }, 213 | }, m) 214 | } 215 | 216 | func (s *DecoderSuite) TestDecodeMessageGet() { 217 | var m Request 218 | 219 | err := NewDecoder(bytes.NewReader(messageGet)).Decode(&m) 220 | s.Assert().NoError(err) 221 | s.Assert().Equal(Request{ 222 | Header: RequestHeader{ 223 | Version: ProtocolVersion{Major: 1, Minor: 1}, 224 | BatchCount: 1, 225 | }, 226 | BatchItems: []RequestBatchItem{ 227 | { 228 | Operation: OPERATION_GET, 229 | RequestPayload: GetRequest{ 230 | UniqueIdentifier: "49a1ca88-6bea-4fb2-b450-7e58802c3038", 231 | }, 232 | }, 233 | }, 234 | }, m) 235 | } 236 | 237 | func TestDecoderSuite(t *testing.T) { 238 | suite.Run(t, new(DecoderSuite)) 239 | } 240 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Package kmip implements KMIP protocol 2 | // 3 | // KMIP protocol is used to access KMS solutions: generating keys, certificates, 4 | // accessing stored objects, etc. 5 | // 6 | // KMIP is using TTLV-like encoding, which is implemented in this packaged 7 | // as encoding/decoding of Go struct types. Go struct fields are annotated with 8 | // `kmip` tags which specify KMIP tag names. Field is encoded/decoded according 9 | // to its tag, type. 10 | // 11 | // Two high-level objects are implemented: Server and Client. Server listens for 12 | // TLS connections, does initial handshake and processes batch requests from the 13 | // clients. Processing of specific operations is delegated to operation handlers. 14 | // Client objects establishes connection with the KMIP server and allows sending 15 | // any number of requests over the connection. 16 | // 17 | // Not all the KMIP operations have corresponding Go structs, missing ones should 18 | // be added to operations.go, and dynamic type dispatch to 19 | // RequestBatchItem/ResponseBatchItem.BuildFieldValue methods. 20 | package kmip 21 | 22 | /* This Source Code Form is subject to the terms of the Mozilla Public 23 | * License, v. 2.0. If a copy of the MPL was not distributed with this 24 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 25 | -------------------------------------------------------------------------------- /encode.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "bytes" 9 | "encoding/binary" 10 | "io" 11 | "reflect" 12 | "time" 13 | 14 | "github.com/pkg/errors" 15 | ) 16 | 17 | // Encoder implements encoding to TTLV KMIP protocol format 18 | // 19 | // All core types are supported: 20 | // 21 | // * Integer (int32) 22 | // * Long Integer (int64) 23 | // * Enumeration (Enum) 24 | // * Boolean (bool) 25 | // * Bytes ([]byte) 26 | // * String (string) 27 | // * Timestamp (time.Time) 28 | // * Interval (time.Duration) 29 | // 30 | // Encoder processes Go structure, analyzing field tags and parsing out 31 | // `kmip` Go struct tags, e.g.: 32 | // Value string `kmip:"TAG_NAME,required"` 33 | // KMIP TAG_NAME is looked up to find tag value, Go type is translated to 34 | // respective KMIP core type (see above), length is automatically calculated. 35 | // 36 | // Fields with zero value which are not required are skipped while encoding. 37 | type Encoder struct { 38 | w io.Writer 39 | } 40 | 41 | // NewEncoder builds encoder writing to w 42 | func NewEncoder(w io.Writer) *Encoder { 43 | return &Encoder{ 44 | w: w, 45 | } 46 | } 47 | 48 | func (e *Encoder) writeTagTypeLength(t Tag, typ Type, l uint32) (err error) { 49 | var ( 50 | b [8]byte 51 | tt [4]byte 52 | ) 53 | 54 | binary.BigEndian.PutUint32(tt[:], uint32(t)) 55 | 56 | copy(b[:3], tt[1:]) 57 | b[3] = byte(typ) 58 | binary.BigEndian.PutUint32(b[4:], l) 59 | 60 | _, err = e.w.Write(b[:]) 61 | return 62 | } 63 | 64 | func (e *Encoder) Encode(v interface{}) (err error) { 65 | rv := reflect.ValueOf(v) 66 | if !rv.IsValid() { 67 | return errors.New("invalid value") 68 | } 69 | if rv.Kind() == reflect.Ptr { 70 | rv = rv.Elem() 71 | } 72 | if !rv.IsValid() { 73 | return errors.New("invalid pointer value") 74 | } 75 | 76 | var structDesc *structDesc 77 | structDesc, err = getStructDesc(rv.Type()) 78 | if err != nil { 79 | return err 80 | } 81 | 82 | err = e.encode(rv, structDesc) 83 | return 84 | } 85 | 86 | func (e *Encoder) encodeValue(f field, rt reflect.Type, rv reflect.Value) (err error) { 87 | if rv.Kind() == reflect.Interface && !rv.IsNil() { 88 | rv = rv.Elem() 89 | if rv.Kind() == reflect.Ptr { 90 | rv = rv.Elem() 91 | } 92 | rt = rv.Type() 93 | 94 | switch rt { 95 | case typeOfInt32: 96 | f.typ = INTEGER 97 | case typeOfInt64: 98 | f.typ = LONG_INTEGER 99 | case typeOfEnum: 100 | f.typ = ENUMERATION 101 | case typeOfBool: 102 | f.typ = BOOLEAN 103 | case typeOfBytes: 104 | f.typ = BYTE_STRING 105 | case typeOfString: 106 | f.typ = TEXT_STRING 107 | case typeOfTime: 108 | f.typ = DATE_TIME 109 | case typeOfDuration: 110 | f.typ = INTERVAL 111 | } 112 | } 113 | 114 | switch f.typ { 115 | case INTEGER: 116 | err = e.writeInteger(f.tag, int32(rv.Int())) 117 | case LONG_INTEGER: 118 | err = e.writeLongInteger(f.tag, rv.Int()) 119 | case ENUMERATION: 120 | err = e.writeEnum(f.tag, Enum(rv.Uint())) 121 | case BOOLEAN: 122 | err = e.writeBool(f.tag, rv.Bool()) 123 | case DATE_TIME: 124 | err = e.writeTime(f.tag, rv.Interface().(time.Time)) 125 | case INTERVAL: 126 | err = e.writeDuration(f.tag, rv.Interface().(time.Duration)) 127 | case BYTE_STRING: 128 | err = e.writeBytes(f.tag, rv.Bytes()) 129 | case TEXT_STRING: 130 | err = e.writeString(f.tag, rv.String()) 131 | case STRUCTURE: 132 | var structDesc *structDesc 133 | 134 | structDesc, err = getStructDesc(rt) 135 | if err != nil { 136 | return 137 | } 138 | 139 | structDesc.tag = f.tag 140 | 141 | err = e.encode(rv, structDesc) 142 | default: 143 | err = errors.Errorf("unsupported type for encode, field %v", f.name) 144 | } 145 | 146 | return 147 | } 148 | 149 | func isZeroValue(rv reflect.Value) (bool, error) { 150 | switch rv.Kind() { 151 | case reflect.Array, reflect.Slice, reflect.String: 152 | return rv.Len() == 0, nil 153 | case reflect.Bool: 154 | return !rv.Bool(), nil 155 | case reflect.Int32, reflect.Int64: 156 | return rv.Int() == 0, nil 157 | case reflect.Uint32: 158 | return rv.Uint() == 0, nil 159 | case reflect.Interface, reflect.Ptr: 160 | return rv.IsNil(), nil 161 | case reflect.Struct: 162 | if rv.Type() == typeOfTime { 163 | return rv.Interface().(time.Time).IsZero(), nil 164 | } 165 | 166 | sD, err := getStructDesc(rv.Type()) 167 | if err != nil { 168 | return false, err 169 | } 170 | 171 | for _, f := range sD.fields { 172 | isZero, err := isZeroValue(rv.FieldByIndex(f.idx)) 173 | if err != nil { 174 | return false, err 175 | } 176 | if !isZero { 177 | return false, nil 178 | } 179 | } 180 | 181 | return true, nil 182 | default: 183 | return false, errors.Errorf("unsupported value for isZeroValue: %v", rv.Kind().String()) 184 | } 185 | } 186 | 187 | func (e *Encoder) encode(rv reflect.Value, sd *structDesc) (err error) { 188 | // build new encoder to encode into temp buf (to know the length) 189 | var buf bytes.Buffer 190 | 191 | ee := NewEncoder(&buf) 192 | 193 | for _, f := range sd.fields { 194 | if f.tag == ANY_TAG || f.skip { 195 | continue 196 | } 197 | 198 | ff := rv.FieldByIndex(f.idx) 199 | 200 | if f.sliceof { 201 | for i := 0; i < ff.Len(); i++ { 202 | err = ee.encodeValue(f, ff.Type().Elem(), ff.Index(i)) 203 | if err != nil { 204 | return 205 | } 206 | } 207 | } else { 208 | if !f.required { 209 | var isZero bool 210 | isZero, err = isZeroValue(ff) 211 | if err != nil { 212 | return 213 | } 214 | 215 | if isZero { 216 | continue 217 | } 218 | } 219 | 220 | err = ee.encodeValue(f, ff.Type(), ff) 221 | if err != nil { 222 | return 223 | } 224 | } 225 | } 226 | 227 | err = e.writeTagTypeLength(sd.tag, STRUCTURE, uint32(buf.Len())) 228 | if err != nil { 229 | return 230 | } 231 | 232 | _, err = io.Copy(e.w, &buf) 233 | return 234 | } 235 | -------------------------------------------------------------------------------- /encode_core.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "encoding/binary" 9 | "time" 10 | ) 11 | 12 | func (e *Encoder) writeInteger(t Tag, v int32) (err error) { 13 | err = e.writeTagTypeLength(t, INTEGER, 4) 14 | if err != nil { 15 | return 16 | } 17 | 18 | var b [8]byte 19 | 20 | binary.BigEndian.PutUint32(b[:4], uint32(v)) 21 | 22 | _, err = e.w.Write(b[:]) 23 | return 24 | } 25 | 26 | func (e *Encoder) writeLongInteger(t Tag, v int64) (err error) { 27 | err = e.writeTagTypeLength(t, LONG_INTEGER, 8) 28 | if err != nil { 29 | return 30 | } 31 | 32 | var b [8]byte 33 | 34 | binary.BigEndian.PutUint64(b[:], uint64(v)) 35 | 36 | _, err = e.w.Write(b[:]) 37 | return 38 | } 39 | 40 | func (e *Encoder) writeEnum(t Tag, v Enum) (err error) { 41 | err = e.writeTagTypeLength(t, ENUMERATION, 4) 42 | if err != nil { 43 | return 44 | } 45 | 46 | var b [8]byte 47 | 48 | binary.BigEndian.PutUint32(b[:4], uint32(v)) 49 | 50 | _, err = e.w.Write(b[:]) 51 | return 52 | } 53 | 54 | func (e *Encoder) writeBool(t Tag, v bool) (err error) { 55 | err = e.writeTagTypeLength(t, BOOLEAN, 8) 56 | if err != nil { 57 | return 58 | } 59 | 60 | var b [8]byte 61 | 62 | if v { 63 | b[7] = 1 64 | } 65 | 66 | _, err = e.w.Write(b[:]) 67 | return 68 | } 69 | 70 | func (e *Encoder) writeByteSlice(t Tag, typ Type, b []byte) (err error) { 71 | err = e.writeTagTypeLength(t, typ, uint32(len(b))) 72 | if err != nil { 73 | return 74 | } 75 | 76 | _, err = e.w.Write(b) 77 | if err != nil { 78 | return 79 | } 80 | 81 | if len(b)%8 != 0 { 82 | var pad [8]byte 83 | 84 | _, err = e.w.Write(pad[:8-len(b)%8]) 85 | } 86 | 87 | return 88 | } 89 | 90 | func (e *Encoder) writeBytes(t Tag, b []byte) error { 91 | return e.writeByteSlice(t, BYTE_STRING, b) 92 | } 93 | 94 | func (e *Encoder) writeString(t Tag, s string) error { 95 | return e.writeByteSlice(t, TEXT_STRING, []byte(s)) 96 | } 97 | 98 | func (e *Encoder) writeTime(t Tag, v time.Time) (err error) { 99 | err = e.writeTagTypeLength(t, DATE_TIME, 8) 100 | if err != nil { 101 | return 102 | } 103 | 104 | var b [8]byte 105 | 106 | binary.BigEndian.PutUint64(b[:], uint64(v.Unix())) 107 | 108 | _, err = e.w.Write(b[:]) 109 | return 110 | } 111 | 112 | func (e *Encoder) writeDuration(t Tag, v time.Duration) (err error) { 113 | err = e.writeTagTypeLength(t, INTERVAL, 4) 114 | if err != nil { 115 | return 116 | } 117 | 118 | var b [8]byte 119 | 120 | binary.BigEndian.PutUint32(b[:4], uint32(v/time.Second)) 121 | 122 | _, err = e.w.Write(b[:]) 123 | return 124 | } 125 | -------------------------------------------------------------------------------- /encode_test.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "bytes" 9 | "encoding/hex" 10 | "strings" 11 | "testing" 12 | "time" 13 | 14 | "github.com/stretchr/testify/suite" 15 | ) 16 | 17 | type EncoderSuite struct { 18 | suite.Suite 19 | } 20 | 21 | func (s *EncoderSuite) parseSpecValue(val string) []byte { 22 | val = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(val, "_", ""), "|", ""), " ", "") 23 | 24 | res, err := hex.DecodeString(val) 25 | s.Require().NoError(err) 26 | 27 | return res 28 | } 29 | 30 | func (s *EncoderSuite) TestWriteInteger() { 31 | var buf bytes.Buffer 32 | 33 | err := NewEncoder(&buf).writeInteger(COMPROMISE_DATE, 8) 34 | s.Assert().NoError(err) 35 | 36 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 02 | 00 00 00 04 | 00 00 00 08 00 00 00 00"), buf.Bytes()) 37 | } 38 | 39 | func (s *EncoderSuite) TestWriteLongInteger() { 40 | var buf bytes.Buffer 41 | 42 | err := NewEncoder(&buf).writeLongInteger(COMPROMISE_DATE, 123456789000000000) 43 | s.Assert().NoError(err) 44 | 45 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 03 | 00 00 00 08 | 01 B6 9B 4B A5 74 92 00"), buf.Bytes()) 46 | } 47 | 48 | func (s *EncoderSuite) TestWriteEnum() { 49 | var buf bytes.Buffer 50 | 51 | err := NewEncoder(&buf).writeEnum(COMPROMISE_DATE, Enum(255)) 52 | s.Assert().NoError(err) 53 | 54 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 05 | 00 00 00 04 | 00 00 00 FF 00 00 00 00"), buf.Bytes()) 55 | } 56 | 57 | func (s *EncoderSuite) TestWriteBool() { 58 | var buf bytes.Buffer 59 | 60 | err := NewEncoder(&buf).writeBool(COMPROMISE_DATE, true) 61 | s.Assert().NoError(err) 62 | 63 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 00 00 00 01"), buf.Bytes()) 64 | } 65 | 66 | func (s *EncoderSuite) TestWriteBytes() { 67 | var buf bytes.Buffer 68 | 69 | err := NewEncoder(&buf).writeBytes(COMPROMISE_DATE, []byte{1, 2, 3}) 70 | s.Assert().NoError(err) 71 | 72 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 08 | 00 00 00 03 | 01 02 03 00 00 00 00 00"), buf.Bytes()) 73 | } 74 | 75 | func (s *EncoderSuite) TestWriteString() { 76 | var buf bytes.Buffer 77 | 78 | err := NewEncoder(&buf).writeString(COMPROMISE_DATE, "Hello World") 79 | s.Assert().NoError(err) 80 | 81 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 07 | 00 00 00 0B | 48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 00"), buf.Bytes()) 82 | } 83 | 84 | func (s *EncoderSuite) TestWriteTime() { 85 | var buf bytes.Buffer 86 | 87 | t, _ := time.Parse(time.RFC3339, "2008-03-14T11:56:40Z") 88 | 89 | err := NewEncoder(&buf).writeTime(COMPROMISE_DATE, t) 90 | s.Assert().NoError(err) 91 | 92 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 09 | 00 00 00 08 | 00 00 00 00 47 DA 67 F8"), buf.Bytes()) 93 | } 94 | 95 | func (s *EncoderSuite) TestWriteInterval() { 96 | var buf bytes.Buffer 97 | 98 | err := NewEncoder(&buf).writeDuration(COMPROMISE_DATE, 10*24*time.Hour) 99 | s.Assert().NoError(err) 100 | 101 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 0A | 00 00 00 04 | 00 0D 2F 00 00 00 00 00"), buf.Bytes()) 102 | } 103 | 104 | func (s *EncoderSuite) TestEncodeStruct() { 105 | var buf bytes.Buffer 106 | 107 | type tt struct { 108 | Tag `kmip:"COMPROMISE_DATE"` 109 | Other string 110 | A Enum `kmip:"APPLICATION_SPECIFIC_INFORMATION,required"` 111 | B int32 `kmip:"ARCHIVE_DATE,required"` 112 | C string `kmip:"COMPROMISE_DATE"` 113 | D []byte `kmip:"ACTIVATION_DATE"` 114 | } 115 | 116 | var v = tt{A: 254, B: 255} 117 | 118 | err := NewEncoder(&buf).Encode(&v) 119 | s.Assert().NoError(err) 120 | 121 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 01 | 00 00 00 20 | 42 00 04 | 05 | 00 00 00 04 | 00 00 00 FE 00 00 00 00 |"+ 122 | " 42 00 05 | 02 | 00 00 00 04 | 00 00 00 FF 00 00 00 00"), buf.Bytes()) 123 | } 124 | 125 | func (s *EncoderSuite) TestEncodeStructWithTimeInterval() { 126 | var buf bytes.Buffer 127 | 128 | type tt struct { 129 | Tag `kmip:"COMPROMISE_DATE"` 130 | A time.Time `kmip:"ARCHIVE_DATE"` 131 | B time.Duration `kmip:"ACTIVATION_DATE"` 132 | } 133 | 134 | t, _ := time.Parse(time.RFC3339, "2008-03-14T11:56:40Z") 135 | var v = tt{A: t, B: 10 * 24 * time.Hour} 136 | 137 | err := NewEncoder(&buf).Encode(&v) 138 | s.Assert().NoError(err) 139 | 140 | s.Assert().EqualValues(s.parseSpecValue("42 00 20 | 01 | 00 00 00 20 | 42 00 05 | 09 | 00 00 00 08 | 00 00 00 00 47 DA 67 F8 |"+ 141 | " 42 00 01 | 0A | 00 00 00 04 | 00 0D 2F 00 00 00 00 00"), buf.Bytes()) 142 | } 143 | 144 | func (s *EncoderSuite) TestEncodeMessageCreate() { 145 | var buf bytes.Buffer 146 | 147 | createRequest := Request{ 148 | Header: RequestHeader{ 149 | Version: ProtocolVersion{Major: 1, Minor: 1}, 150 | BatchCount: 1, 151 | }, 152 | BatchItems: []RequestBatchItem{ 153 | { 154 | Operation: OPERATION_CREATE, 155 | RequestPayload: CreateRequest{ 156 | ObjectType: OBJECT_TYPE_SYMMETRIC_KEY, 157 | TemplateAttribute: TemplateAttribute{ 158 | Attributes: []Attribute{ 159 | { 160 | Name: ATTRIBUTE_NAME_CRYPTOGRAPHIC_ALGORITHM, 161 | Value: CRYPTO_AES, 162 | }, 163 | { 164 | Name: ATTRIBUTE_NAME_CRYPTOGRAPHIC_LENGTH, 165 | Value: int32(128), 166 | }, 167 | { 168 | Name: ATTRIBUTE_NAME_CRYPTOGRAPHIC_USAGE_MASK, 169 | Value: int32(12), 170 | }, 171 | { 172 | Name: ATTRIBUTE_NAME_INITIAL_DATE, 173 | Value: time.Unix(12345, 0), 174 | }, 175 | }, 176 | }, 177 | }, 178 | }, 179 | }, 180 | } 181 | 182 | err := NewEncoder(&buf).Encode(&createRequest) 183 | s.Assert().NoError(err) 184 | 185 | s.Assert().EqualValues(messageCreate, buf.Bytes()) 186 | } 187 | 188 | func (s *EncoderSuite) TestEncodeMessageGet() { 189 | var buf bytes.Buffer 190 | 191 | getRequest := Request{ 192 | Header: RequestHeader{ 193 | Version: ProtocolVersion{Major: 1, Minor: 1}, 194 | BatchCount: 1, 195 | }, 196 | BatchItems: []RequestBatchItem{ 197 | { 198 | Operation: OPERATION_GET, 199 | RequestPayload: GetRequest{ 200 | UniqueIdentifier: "49a1ca88-6bea-4fb2-b450-7e58802c3038", 201 | }, 202 | }, 203 | }, 204 | } 205 | 206 | err := NewEncoder(&buf).Encode(&getRequest) 207 | s.Assert().NoError(err) 208 | 209 | s.Assert().EqualValues(messageGet, buf.Bytes()) 210 | } 211 | 212 | func (s *EncoderSuite) TestEncodeMessageGetPointer() { 213 | var buf bytes.Buffer 214 | 215 | getRequest := Request{ 216 | Header: RequestHeader{ 217 | Version: ProtocolVersion{Major: 1, Minor: 1}, 218 | BatchCount: 1, 219 | }, 220 | BatchItems: []RequestBatchItem{ 221 | { 222 | Operation: OPERATION_GET, 223 | RequestPayload: &GetRequest{ 224 | UniqueIdentifier: "49a1ca88-6bea-4fb2-b450-7e58802c3038", 225 | }, 226 | }, 227 | }, 228 | } 229 | 230 | err := NewEncoder(&buf).Encode(&getRequest) 231 | s.Assert().NoError(err) 232 | 233 | s.Assert().EqualValues(messageGet, buf.Bytes()) 234 | } 235 | 236 | func TestEncoderSuite(t *testing.T) { 237 | suite.Run(t, new(EncoderSuite)) 238 | } 239 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | // Error enhances error with "Result Reason" field 8 | // 9 | // Any Error instance is returned back to the caller with message and 10 | // result reason set, any other Go error is returned as "General Failure" 11 | type Error interface { 12 | error 13 | ResultReason() Enum 14 | } 15 | 16 | type protocolError struct { 17 | error 18 | reason Enum 19 | } 20 | 21 | func (e protocolError) ResultReason() Enum { 22 | return e.reason 23 | } 24 | 25 | func wrapError(err error, reason Enum) protocolError { 26 | return protocolError{err, reason} 27 | } 28 | -------------------------------------------------------------------------------- /fields.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "reflect" 9 | "strings" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | type field struct { 15 | name string 16 | idx []int 17 | tag Tag 18 | typ Type 19 | required bool 20 | sliceof bool 21 | skip bool 22 | dynamic bool 23 | } 24 | 25 | type structDesc struct { 26 | tag Tag 27 | 28 | fields []field 29 | } 30 | 31 | func parseTag(tag string) (name, opt string) { 32 | parts := strings.SplitN(tag, ",", 2) 33 | name = parts[0] 34 | if len(parts) > 1 { 35 | opt = parts[1] 36 | } 37 | 38 | return 39 | } 40 | 41 | func guessType(ft reflect.Type, f *field) error { 42 | switch ft { 43 | case typeOfInt32: 44 | f.typ = INTEGER 45 | case typeOfInt64: 46 | f.typ = LONG_INTEGER 47 | case typeOfEnum: 48 | f.typ = ENUMERATION 49 | case typeOfBool: 50 | f.typ = BOOLEAN 51 | case typeOfBytes: 52 | f.typ = BYTE_STRING 53 | case typeOfString: 54 | f.typ = TEXT_STRING 55 | case typeOfTime: 56 | f.typ = DATE_TIME 57 | case typeOfDuration: 58 | f.typ = INTERVAL 59 | default: 60 | if ft.Kind() == reflect.Struct { 61 | f.typ = STRUCTURE 62 | } else if ft.Kind() == reflect.Interface { 63 | f.typ = STRUCTURE 64 | f.dynamic = true 65 | } else { 66 | return errors.Errorf("unsupported type %s", ft.String()) 67 | } 68 | } 69 | 70 | return nil 71 | } 72 | 73 | func getStructDesc(tt reflect.Type) (*structDesc, error) { 74 | res := &structDesc{} 75 | 76 | for i := 0; i < tt.NumField(); i++ { 77 | ff := tt.Field(i) 78 | 79 | name, opt := parseTag(ff.Tag.Get("kmip")) 80 | 81 | if ff.Type == typeOfTag { 82 | var ok bool 83 | if res.tag, ok = tagMap[name]; !ok { 84 | return nil, errors.Errorf("unknown tag %v for struct tag", name) 85 | } 86 | continue 87 | } 88 | 89 | if name == "" || ff.PkgPath != "" { 90 | continue 91 | } 92 | 93 | f := field{ 94 | name: ff.Name, 95 | idx: ff.Index, 96 | } 97 | 98 | var ok bool 99 | if f.tag, ok = tagMap[name]; !ok { 100 | return nil, errors.Errorf("unknown tag %v for field %v", name, ff.Name) 101 | } 102 | 103 | f.required = strings.Contains(opt, "required") 104 | f.skip = strings.Contains(opt, "skip") 105 | 106 | ft := ff.Type 107 | if ft.Kind() == reflect.Slice && ft != typeOfBytes { 108 | f.sliceof = true 109 | ft = ft.Elem() 110 | } 111 | 112 | if err := guessType(ft, &f); err != nil { 113 | return nil, errors.WithMessagef(err, "error processing field %v", ff.Name) 114 | } 115 | 116 | res.fields = append(res.fields, f) 117 | } 118 | 119 | return res, nil 120 | } 121 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/smira/go-kmip 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/pkg/errors v0.9.1 7 | github.com/stretchr/testify v1.7.0 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 4 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 5 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 6 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 12 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 13 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 14 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 15 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 16 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 17 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 18 | -------------------------------------------------------------------------------- /keys.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | // KeyWrappingSpecification is a Key Wrapping Specification Object 8 | type KeyWrappingSpecification struct { 9 | Tag `kmip:"KEY_WRAPPING_SPECIFICATION"` 10 | 11 | WrappingMethod Enum `kmip:"WRAPPING_METHOD,required"` 12 | EncryptionKeyInformation EncryptionKeyInformation `kmip:"ENCRYPTION_KEY_INFORMATION"` 13 | MACSignatureKeyInformation MACSignatureKeyInformation `kmip:"MAC_SIGNATURE_KEY_INFORMATION"` 14 | AttributeName []string `kmip:"ATTRIBUTE_NAME"` 15 | EncodingOption Enum `kmip:"ENCODING_OPTION"` 16 | } 17 | 18 | // KeyWrappingData is a Key Wrapping Data Object Structure 19 | type KeyWrappingData struct { 20 | Tag `kmip:"KEY_WRAPPING_DATA"` 21 | 22 | WrappingMethod Enum `kmip:"WRAPPING_METHOD,required"` 23 | EncryptionKeyInformation EncryptionKeyInformation `kmip:"ENCRYPTION_KEY_INFORMATION"` 24 | MACSignatureKeyInformation MACSignatureKeyInformation `kmip:"MAC_SIGNATURE_KEY_INFORMATION"` 25 | MACSignature []byte `kmip:"MAC_SIGNATURE"` 26 | IVCounterNonce []byte `kmip:"IV_COUNTER_NONCE"` 27 | EncodingOption Enum `kmip:"ENCODING_OPTION"` 28 | } 29 | 30 | // EncryptionKeyInformation is a Key Wrapping Specification Object 31 | type EncryptionKeyInformation struct { 32 | Tag `kmip:"ENCRYPTION_KEY_INFORMATION"` 33 | 34 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 35 | CryptoParams CryptoParams `kmip:"CRYPTOGRAPHIC_PARAMETERS"` 36 | } 37 | 38 | // MACSignatureKeyInformation is a MAC/Signature Key Information Object Structure 39 | type MACSignatureKeyInformation struct { 40 | Tag `kmip:"MAC_SIGNATURE_KEY_INFORMATION"` 41 | 42 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 43 | CryptoParams CryptoParams `kmip:"CRYPTOGRAPHIC_PARAMETERS"` 44 | } 45 | 46 | // CryptoParams is a Cryptographic Parameters Attribute Structure 47 | type CryptoParams struct { 48 | Tag `kmip:"CRYPTOGRAPHIC_PARAMETERS"` 49 | 50 | BlockCipherMode Enum `kmip:"BLOCK_CIPHER_MODE"` 51 | PaddingMethod Enum `kmip:"PADDING_METHOD"` 52 | HashingAlgorithm Enum `kmip:"HASHING_ALGORITHM"` 53 | KeyRoleType Enum `kmip:"KEY_ROLE_TYPE"` 54 | DigitalSignatureAlgorithm Enum `kmip:"DIGITAL_SIGNATURE_ALGORITHM"` 55 | CryptographicAlgorithm Enum `kmip:"CRYPTOGRAPHIC_ALGORITHM"` 56 | RandomIV bool `kmip:"RANDOM_IV"` 57 | IVLength int32 `kmip:"IV_LENGTH"` 58 | TagLength int32 `kmip:"TAG_LENGTH"` 59 | FixedFieldLength int32 `kmip:"FIXED_FIELD_LENGTH"` 60 | InvocationFieldLength int32 `kmip:"INVOCATION_FIELD_LENGTH"` 61 | CounterLength int32 `kmip:"COUNTER_LENGTH"` 62 | InitialCounterValue int32 `kmip:"INITIAL_COUNTER_VALUE"` 63 | SaltLength int32 `kmip:"SALT_LENGTH"` 64 | MaskGenerator Enum `kmip:"MASK_GENERATOR"` 65 | MaskGeneratorHashingAlgorithm Enum `kmip:"MASK_GENERATOR_HASHING_ALGORITHM"` 66 | PSource []byte `kmip:"P_SOURCE"` 67 | TrailerFIeld int32 `kmip:"TRAILER_FIELD"` 68 | } 69 | 70 | // SymmetricKey is a Managed Cryptographic Object that is a symmetric key 71 | type SymmetricKey struct { 72 | Tag `kmip:"SYMMETRIC_KEY"` 73 | 74 | KeyBlock KeyBlock `kmip:"KEY_BLOCK,required"` 75 | } 76 | 77 | // PublicKey is a Managed Cryptographic Object that is a public key 78 | type PublicKey struct { 79 | Tag `kmip:"PUBLIC_KEY"` 80 | 81 | KeyBlock KeyBlock `kmip:"KEY_BLOCK,required"` 82 | } 83 | 84 | // PrivateKey is a Managed Cryptographic Object that is a private key 85 | type PrivateKey struct { 86 | Tag `kmip:"PRIVATE_KEY"` 87 | 88 | KeyBlock KeyBlock `kmip:"KEY_BLOCK,required"` 89 | } 90 | 91 | // KeyBlock is a Key Block Object Structure 92 | type KeyBlock struct { 93 | Tag `kmip:"KEY_BLOCK"` 94 | 95 | FormatType Enum `kmip:"KEY_FORMAT_TYPE,required"` 96 | CompressionType Enum `kmip:"KEY_COMPRESSION_TYPE"` 97 | Value KeyValue `kmip:"KEY_VALUE,required"` 98 | CryptographicAlgorithm Enum `kmip:"CRYPTOGRAPHIC_ALGORITHM"` 99 | CryptographicLength int32 `kmip:"CRYPTOGRAPHIC_LENGTH"` 100 | WrappingData KeyWrappingData `kmip:"KEY_WRAPPING_SPECIFICATION"` 101 | } 102 | 103 | // KeyValue is a Key Value Object Structure 104 | type KeyValue struct { 105 | Tag `kmip:"KEY_VALUE"` 106 | 107 | // TODO: might be structure if wrapping is used 108 | KeyMaterial []byte `kmip:"KEY_MATERIAL"` 109 | Attributes Attributes `kmip:"ATTRIBUTE"` 110 | } 111 | -------------------------------------------------------------------------------- /operations.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | /* This Source Code Form is subject to the terms of the Mozilla Public 8 | * License, v. 2.0. If a copy of the MPL was not distributed with this 9 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 10 | 11 | // CreateRequest is a Create Request Payload 12 | type CreateRequest struct { 13 | ObjectType Enum `kmip:"OBJECT_TYPE,required"` 14 | TemplateAttribute TemplateAttribute `kmip:"TEMPLATE_ATTRIBUTE,required"` 15 | } 16 | 17 | // CreateResponse is a Create Response Payload 18 | type CreateResponse struct { 19 | ObjectType Enum `kmip:"OBJECT_TYPE,required"` 20 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 21 | TemplateAttribute TemplateAttribute `kmip:"TEMPLATE_ATTRIBUTE"` 22 | } 23 | 24 | // CreateKeyPairRequest is a Create Key Pair Request Payload 25 | type CreateKeyPairRequest struct { 26 | CommonTemplateAttribute TemplateAttribute `kmip:"COMMON_TEMPLATE_ATTRIBUTE"` 27 | PrivateKeyTemplateAttribute TemplateAttribute `kmip:"PRIVATE_KEY_TEMPLATE_ATTRIBUTE"` 28 | PublicKeyTemplateAttribute TemplateAttribute `kmip:"PUBLIC_KEY_TEMPLATE_ATTRIBUTE"` 29 | } 30 | 31 | // CreateKeyPairResponse is a Create Key Pair Response Payload 32 | type CreateKeyPairResponse struct { 33 | PrivateKeyUniqueIdentifier string `kmip:"PRIVATE_KEY_UNIQUE_IDENTIFIER,required"` 34 | PublicKeyUniqueIdentifier string `kmip:"PUBLIC_KEY_UNIQUE_IDENTIFIER,required"` 35 | PrivateKeyTemplateAttribute TemplateAttribute `kmip:"PRIVATE_KEY_TEMPLATE_ATTRIBUTE"` 36 | PublicKeyTemplateAttribute TemplateAttribute `kmip:"PUBLIC_KEY_TEMPLATE_ATTRIBUTE"` 37 | } 38 | 39 | // GetRequest is a Get Request Payload 40 | type GetRequest struct { 41 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 42 | KeyFormatType Enum `kmip:"KEY_FORMAT_TYPE"` 43 | KeyWrapType Enum `kmip:"KEY_WRAP_TYPE"` 44 | KeyCompressionType Enum `kmip:"KEY_COMPRESSION_TYPE"` 45 | KeyWrappingSpec KeyWrappingSpecification `kmip:"KEY_WRAPPING_SPECIFICATION"` 46 | } 47 | 48 | // GetResponse is a Get Response Payload 49 | type GetResponse struct { 50 | ObjectType Enum `kmip:"OBJECT_TYPE,required"` 51 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 52 | // Response might contain one of SymmetricKey, Certificate, ... 53 | SymmetricKey SymmetricKey `kmip:"SYMMETRIC_KEY"` 54 | PrivateKey PrivateKey `kmip:"PRIVATE_KEY"` 55 | PublicKey PublicKey `kmip:"PUBLIC_KEY"` 56 | } 57 | 58 | // GetAttributesRequest is a Get Attributes Request Payload 59 | type GetAttributesRequest struct { 60 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 61 | AttributeNames []string `kmip:"ATTRIBUTE_NAME"` 62 | } 63 | 64 | // GetAttributesResponse is a Get Attributes Response Payload 65 | type GetAttributesResponse struct { 66 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 67 | Attributes Attributes `kmip:"ATTRIBUTE"` 68 | } 69 | 70 | // GetAttributeListRequest is a Get Attribute List Request Payload 71 | type GetAttributeListRequest struct { 72 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 73 | } 74 | 75 | // GetAttributeListResponse is a Get Attribute List Response Payload 76 | type GetAttributeListResponse struct { 77 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 78 | AttributeNames []string `kmip:"ATTRIBUTE_NAME"` 79 | } 80 | 81 | // ActivateRequest is a Activate Request Payload 82 | type ActivateRequest struct { 83 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 84 | } 85 | 86 | // ActivateResponse is a Activate Response Payload 87 | type ActivateResponse struct { 88 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 89 | } 90 | 91 | // RevokeRequest is a Revoke Request Payload 92 | type RevokeRequest struct { 93 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 94 | RevocationReason RevocationReason `kmip:"REVOCATION_REASON,required"` 95 | CompromiseDate time.Time `kmip:"COMPROMISE_DATE"` 96 | } 97 | 98 | // RevokeResponse is a Revoke Response Payload 99 | type RevokeResponse struct { 100 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 101 | } 102 | 103 | // DestroyRequest is a Destroy Request Payload 104 | type DestroyRequest struct { 105 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 106 | } 107 | 108 | // DestroyResponse is a Destroy Response Payload 109 | type DestroyResponse struct { 110 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 111 | } 112 | 113 | // DiscoverVersionsRequest is a Discover Versions Request Payload 114 | type DiscoverVersionsRequest struct { 115 | ProtocolVersions []ProtocolVersion `kmip:"PROTOCOL_VERSION"` 116 | } 117 | 118 | // DiscoverVersionsResponse is a Discover Versions Response Payload 119 | type DiscoverVersionsResponse struct { 120 | ProtocolVersions []ProtocolVersion `kmip:"PROTOCOL_VERSION"` 121 | } 122 | 123 | // QueryRequest is a Query Request Payload 124 | type QueryRequest struct { 125 | QueryFunctions []Enum `kmip:"QUERY_FUNCTION,required"` 126 | } 127 | 128 | // QueryResponse is a Query Response Payload 129 | type QueryResponse struct { 130 | Operations []Enum `kmip:"OPERATION"` 131 | ObjectTypes []Enum `kmip:"OBJECT_TYPE"` 132 | VendorIdentification string `kmip:"VENDOR_IDENTIFICATION"` 133 | } 134 | 135 | // EncryptRequest is an Encrypt Request Payload 136 | type EncryptRequest struct { 137 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 138 | CryptoParams CryptoParams `kmip:"CRYPTOGRAPHIC_PARAMETERS"` 139 | Data []byte `kmip:"DATA"` 140 | IVCounterNonce []byte `kmip:"IV_COUNTER_NONCE"` 141 | CorrelationValue []byte `kmip:"CORRELATION_VALUE"` 142 | InitIndicator bool `kmip:"INIT_INDICATOR"` 143 | FinalIndicator bool `kmip:"FINAL_INDICATOR"` 144 | AdditionalData []byte `kmip:"AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA"` 145 | } 146 | 147 | // EncryptResponse is a Encrypt Response Payload 148 | type EncryptResponse struct { 149 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 150 | Data []byte `kmip:"DATA"` 151 | IVCounterNonce []byte `kmip:"IV_COUNTER_NONCE"` 152 | CorrelationValue []byte `kmip:"CORRELATION_VALUE"` 153 | AuthTag []byte `kmip:"AUTHENTICATED_ENCRYPTION_TAG"` 154 | } 155 | 156 | // DecryptRequest is a Decrypt Request Payload 157 | type DecryptRequest struct { 158 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 159 | CryptoParams CryptoParams `kmip:"CRYPTOGRAPHIC_PARAMETERS"` 160 | Data []byte `kmip:"DATA"` 161 | IVCounterNonce []byte `kmip:"IV_COUNTER_NONCE"` 162 | CorrelationValue []byte `kmip:"CORRELATION_VALUE"` 163 | InitIndicator bool `kmip:"INIT_INDICATOR"` 164 | FinalIndicator bool `kmip:"FINAL_INDICATOR"` 165 | AdditionalData []byte `kmip:"AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA"` 166 | AuthTag []byte `kmip:"AUTHENTICATED_ENCRYPTION_TAG"` 167 | } 168 | 169 | // DecryptResponse is a Decrypt Response Payload 170 | type DecryptResponse struct { 171 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 172 | Data []byte `kmip:"DATA"` 173 | CorrelationValue []byte `kmip:"CORRELATION_VALUE"` 174 | } 175 | 176 | // SignRequest is a Sign Request Payload 177 | type SignRequest struct { 178 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER"` 179 | CryptoParams CryptoParams `kmip:"CRYPTOGRAPHIC_PARAMETERS"` 180 | Data []byte `kmip:"DATA"` 181 | CorrelationValue []byte `kmip:"CORRELATION_VALUE"` 182 | InitIndicator bool `kmip:"INIT_INDICATOR"` 183 | FinalIndicator bool `kmip:"FINAL_INDICATOR"` 184 | } 185 | 186 | // SignResponse is a Sign Response Payload 187 | type SignResponse struct { 188 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 189 | SignatureData []byte `kmip:"SIGNATURE_DATA"` 190 | CorrelationValue []byte `kmip:"CORRELATION_VALUE"` 191 | } 192 | 193 | // RegisterRequest is a Register Request Payload 194 | type RegisterRequest struct { 195 | ObjectType Enum `kmip:"OBJECT_TYPE,required"` 196 | TemplateAttribute TemplateAttribute `kmip:"TEMPLATE_ATTRIBUTE,required"` 197 | // Request might contain one of SymmetricKey, Certificate, ... 198 | SymmetricKey SymmetricKey `kmip:"SYMMETRIC_KEY"` 199 | PrivateKey PrivateKey `kmip:"PRIVATE_KEY"` 200 | PublicKey PublicKey `kmip:"PUBLIC_KEY"` 201 | } 202 | 203 | // RegisterResponse is a Register Response Payload 204 | type RegisterResponse struct { 205 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 206 | TemplateAttribute TemplateAttribute `kmip:"TEMPLATE_ATTRIBUTE"` 207 | } 208 | 209 | // LocateRequest is a Locate Request Payload 210 | type LocateRequest struct { 211 | MaximumItems int32 `kmip:"MAXIMUM_ITEMS"` 212 | OffsetItems int32 `kmip:"OFFSET_ITEMS"` 213 | StorageStatusMask int32 `kmip:"STORAGE_STATUS_MASK"` 214 | ObjectGroupMember Enum `kmip:"OBJECT_GROUP_MEMBER"` 215 | Attributes Attributes `kmip:"ATTRIBUTE"` 216 | } 217 | 218 | // LocateResponse is a Locate Response Payload 219 | type LocateResponse struct { 220 | LocatedItems int32 `kmip:"LOCATED_ITEMS"` 221 | UniqueIdentifiers []string `kmip:"UNIQUE_IDENTIFIER"` 222 | } 223 | type ReKeyRequest struct { 224 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 225 | } 226 | 227 | type ReKeyResponse struct { 228 | UniqueIdentifier string `kmip:"UNIQUE_IDENTIFIER,required"` 229 | } 230 | -------------------------------------------------------------------------------- /request.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "time" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | // Request is a Request Message Structure 14 | type Request struct { 15 | Tag `kmip:"REQUEST_MESSAGE"` 16 | 17 | Header RequestHeader `kmip:"REQUEST_HEADER,required"` 18 | BatchItems []RequestBatchItem `kmip:"REQUEST_BATCH_ITEM,required"` 19 | } 20 | 21 | // RequestHeader is a Request Header Structure 22 | type RequestHeader struct { 23 | Tag `kmip:"REQUEST_HEADER"` 24 | 25 | Version ProtocolVersion `kmip:"PROTOCOL_VERSION,required"` 26 | MaxResponseSize int32 `kmip:"MAXIMUM_RESPONSE_SIZE"` 27 | ClientCorrelationValue string `kmip:"CLIENT_CORRELATION_VALUE"` 28 | ServerCorrelationValue string `kmip:"SERVER_CORRELATION_VALUE"` 29 | AsynchronousIndicator bool `kmip:"ASYNCHRONOUS_INDICATOR"` 30 | AttestationCapableIndicator bool `kmip:"ATTESTATION_CAPABLE_INDICATOR"` 31 | AttestationType []Enum `kmip:"ATTESTATION_TYPE"` 32 | Authentication Authentication `kmip:"AUTHENTICATION"` 33 | BatchErrorContinuationOption Enum `kmip:"BATCH_ERROR_CONTINUATION_OPTION"` 34 | BatchOrderOption bool `kmip:"BATCH_ORDER_OPTION"` 35 | TimeStamp time.Time `kmip:"TIME_STAMP"` 36 | BatchCount int32 `kmip:"BATCH_COUNT,required"` 37 | } 38 | 39 | // RequestBatchItem is a Request Batch Item Structure 40 | type RequestBatchItem struct { 41 | Tag `kmip:"REQUEST_BATCH_ITEM"` 42 | 43 | Operation Enum `kmip:"OPERATION,required"` 44 | UniqueID []byte `kmip:"UNIQUE_BATCH_ITEM_ID"` 45 | RequestPayload interface{} `kmip:"REQUEST_PAYLOAD,required"` 46 | MessageExtension MessageExtension `kmip:"MESSAGE_EXTENSION"` 47 | } 48 | 49 | // BuildFieldValue builds value for RequestPayload based on Operation 50 | func (bi *RequestBatchItem) BuildFieldValue(name string) (v interface{}, err error) { 51 | switch bi.Operation { 52 | case OPERATION_CREATE: 53 | v = &CreateRequest{} 54 | case OPERATION_GET: 55 | v = &GetRequest{} 56 | case OPERATION_GET_ATTRIBUTES: 57 | v = &GetAttributesRequest{} 58 | case OPERATION_GET_ATTRIBUTE_LIST: 59 | v = &GetAttributeListRequest{} 60 | case OPERATION_DESTROY: 61 | v = &DestroyRequest{} 62 | case OPERATION_DISCOVER_VERSIONS: 63 | v = &DiscoverVersionsRequest{} 64 | case OPERATION_REGISTER: 65 | v = &RegisterRequest{} 66 | case OPERATION_ACTIVATE: 67 | v = &ActivateRequest{} 68 | case OPERATION_LOCATE: 69 | v = &LocateRequest{} 70 | case OPERATION_REVOKE: 71 | v = &RevokeRequest{} 72 | default: 73 | err = errors.Errorf("unsupported operation: %v", bi.Operation) 74 | } 75 | 76 | return 77 | } 78 | 79 | // ProtocolVersion is a Protocol Version structure 80 | type ProtocolVersion struct { 81 | Tag `kmip:"PROTOCOL_VERSION"` 82 | 83 | Major int32 `kmip:"PROTOCOL_VERSION_MAJOR"` 84 | Minor int32 `kmip:"PROTOCOL_VERSION_MINOR"` 85 | } 86 | 87 | // MessageExtension is a Message Extension structure in a Batch Item 88 | type MessageExtension struct { 89 | Tag `kmip:"MESSAGE_EXTENSION"` 90 | 91 | VendorIdentification string `kmip:"VENDOR_IDENTIFICATION,required"` 92 | CriticalityIndicator bool `kmip:"CRITICALITY_INDICATOR,required"` 93 | VendorExtension interface{} `kmip:"-,skip"` 94 | } 95 | 96 | // RevocationReason is a Revocation Reason structure 97 | type RevocationReason struct { 98 | Tag `kmip:"REVOCATION_REASON"` 99 | 100 | RevocationReasonCode Enum `kmip:"REVOCATION_REASON_CODE"` 101 | RevocationMessage string `kmip:"REVOCATION_REASON"` 102 | } 103 | -------------------------------------------------------------------------------- /request_test.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | var ( 8 | messageCreate = []byte("\x42\x00\x78\x01\x00\x00\x01\x50\x42\x00\x77\x01\x00\x00\x00\x38\x42\x00\x69\x01\x00\x00\x00\x20\x42\x00\x6A\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x6B\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x0D\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x0F\x01\x00\x00\x01\x08\x42\x00\x5C\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x79\x01\x00\x00\x00\xF0\x42\x00\x57\x05\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x42\x00\x91\x01\x00\x00\x00\xD8\x42\x00\x08\x01\x00\x00\x00\x30\x42\x00\x0A\x07\x00\x00\x00\x17\x43\x72\x79\x70\x74\x6F\x67\x72\x61\x70\x68\x69\x63\x20\x41\x6C\x67\x6F\x72\x69\x74\x68\x6D\x00\x42\x00\x0B\x05\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x00\x42\x00\x08\x01\x00\x00\x00\x30\x42\x00\x0A\x07\x00\x00\x00\x14\x43\x72\x79\x70\x74\x6F\x67\x72\x61\x70\x68\x69\x63\x20\x4C\x65\x6E\x67\x74\x68\x00\x00\x00\x00\x42\x00\x0B\x02\x00\x00\x00\x04\x00\x00\x00\x80\x00\x00\x00\x00\x42\x00\x08\x01\x00\x00\x00\x30\x42\x00\x0A\x07\x00\x00\x00\x18\x43\x72\x79\x70\x74\x6F\x67\x72\x61\x70\x68\x69\x63\x20\x55\x73\x61\x67\x65\x20\x4D\x61\x73\x6B\x42\x00\x0B\x02\x00\x00\x00\x04\x00\x00\x00\x0C\x00\x00\x00\x00\x42\x00\x08\x01\x00\x00\x00\x28\x42\x00\x0A\x07\x00\x00\x00\x0C\x49\x6E\x69\x74\x69\x61\x6C\x20\x44\x61\x74\x65\x00\x00\x00\x00\x42\x00\x0B\x09\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x30\x39") 9 | messageGet = []byte("\x42\x00\x78\x01\x00\x00\x00\x90\x42\x00\x77\x01\x00\x00\x00\x38\x42\x00\x69\x01\x00\x00\x00\x20\x42\x00\x6A\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x6B\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x0D\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x42\x00\x0F\x01\x00\x00\x00\x48\x42\x00\x5C\x05\x00\x00\x00\x04\x00\x00\x00\x0A\x00\x00\x00\x00\x42\x00\x79\x01\x00\x00\x00\x30\x42\x00\x94\x07\x00\x00\x00\x24\x34\x39\x61\x31\x63\x61\x38\x38\x2D\x36\x62\x65\x61\x2D\x34\x66\x62\x32\x2D\x62\x34\x35\x30\x2D\x37\x65\x35\x38\x38\x30\x32\x63\x33\x30\x33\x38\x00\x00\x00\x00") 10 | ) 11 | -------------------------------------------------------------------------------- /response.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "time" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | // Response is a Response Message Structure 14 | type Response struct { 15 | Tag `kmip:"RESPONSE_MESSAGE"` 16 | 17 | Header ResponseHeader `kmip:"RESPONSE_HEADER,required"` 18 | BatchItems []ResponseBatchItem `kmip:"RESPONSE_BATCH_ITEM,required"` 19 | } 20 | 21 | // ResponseHeader is a Response Header Structure 22 | type ResponseHeader struct { 23 | Tag `kmip:"RESPONSE_HEADER"` 24 | 25 | Version ProtocolVersion `kmip:"PROTOCOL_VERSION,required"` 26 | TimeStamp time.Time `kmip:"TIME_STAMP,required"` 27 | Nonce Nonce `kmip:"NONCE"` 28 | AttestationType []Enum `kmip:"ATTESTATION_TYPE"` 29 | ClientCorrelationValue string `kmip:"CLIENT_CORRELATION_VALUE"` 30 | ServerCorrelationValue string `kmip:"SERVER_CORRELATION_VALUE"` 31 | BatchCount int32 `kmip:"BATCH_COUNT,required"` 32 | } 33 | 34 | // ResponseBatchItem is a Response Batch Item Structure 35 | type ResponseBatchItem struct { 36 | Operation Enum `kmip:"OPERATION,required"` 37 | UniqueID []byte `kmip:"UNIQUE_BATCH_ITEM_ID"` 38 | ResultStatus Enum `kmip:"RESULT_STATUS,required"` 39 | ResultReason Enum `kmip:"RESULT_REASON"` 40 | ResultMessage string `kmip:"RESULT_MESSAGE"` 41 | AsyncronousCorrelationValue []byte `kmip:"ASYNCHRONOUS_CORRELATION_VALUE"` 42 | ResponsePayload interface{} `kmip:"RESPONSE_PAYLOAD"` 43 | MessageExtension MessageExtension `kmip:"MESSAGE_EXTENSION"` 44 | } 45 | 46 | // BuildFieldValue builds value for ResponsePayload based on Operation 47 | func (bi *ResponseBatchItem) BuildFieldValue(name string) (v interface{}, err error) { 48 | switch bi.Operation { 49 | case OPERATION_CREATE: 50 | v = &CreateResponse{} 51 | case OPERATION_CREATE_KEY_PAIR: 52 | v = &CreateKeyPairResponse{} 53 | case OPERATION_GET: 54 | v = &GetResponse{} 55 | case OPERATION_GET_ATTRIBUTES: 56 | v = &GetAttributesResponse{} 57 | case OPERATION_GET_ATTRIBUTE_LIST: 58 | v = &GetAttributeListResponse{} 59 | case OPERATION_ACTIVATE: 60 | v = &ActivateResponse{} 61 | case OPERATION_REVOKE: 62 | v = &RevokeResponse{} 63 | case OPERATION_DESTROY: 64 | v = &DestroyResponse{} 65 | case OPERATION_DISCOVER_VERSIONS: 66 | v = &DiscoverVersionsResponse{} 67 | case OPERATION_ENCRYPT: 68 | v = &EncryptResponse{} 69 | case OPERATION_DECRYPT: 70 | v = &DecryptResponse{} 71 | case OPERATION_SIGN: 72 | v = &SignResponse{} 73 | case OPERATION_REGISTER: 74 | v = &RegisterResponse{} 75 | case OPERATION_LOCATE: 76 | v = &LocateResponse{} 77 | case OPERATION_REKEY: 78 | v = &ReKeyResponse{} 79 | default: 80 | err = errors.Errorf("unsupported operation: %v", bi.Operation) 81 | } 82 | 83 | return 84 | } 85 | 86 | // Nonce object is a structure used by the server to send a random value to the client 87 | type Nonce struct { 88 | Tag `kmip:"NONCE"` 89 | 90 | NonceID []byte `kmip:"NONCE_ID,required"` 91 | NonceValue []byte `kmip:"NONCE_VALUE,required"` 92 | } 93 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "context" 9 | "crypto/tls" 10 | "fmt" 11 | "io" 12 | "io/ioutil" 13 | "log" 14 | "net" 15 | "runtime" 16 | "sync" 17 | "time" 18 | 19 | "github.com/pkg/errors" 20 | ) 21 | 22 | // Server implements core KMIP server 23 | type Server struct { 24 | // Listen address 25 | Addr string 26 | 27 | // TLS Configuration for the server 28 | TLSConfig *tls.Config 29 | 30 | // Log destination (if not set, log is discarded) 31 | Log *log.Logger 32 | 33 | // Supported version of KMIP, in the order of the preference 34 | // 35 | // If not set, defaults to DefaultSupportedVersions 36 | SupportedVersions []ProtocolVersion 37 | 38 | // Network read & write timeouts 39 | // 40 | // If set to zero, timeouts are not enforced 41 | ReadTimeout time.Duration 42 | WriteTimeout time.Duration 43 | 44 | // SessionAuthHandler is called after TLS handshake 45 | // 46 | // This handler might additionally verify client TLS cert or perform 47 | // any other kind of auth (say, by soure address) 48 | SessionAuthHandler func(conn net.Conn) (sessionAuth interface{}, err error) 49 | 50 | // RequestAuthHandler is called for any request which has Authentication field set 51 | // 52 | // Value returned from RequestAuthHandler is stored as RequestContext.RequestAuth, which 53 | // can be used to authorize each batch item in the request 54 | RequestAuthHandler func(sesssion *SessionContext, auth *Authentication) (requestAuth interface{}, err error) 55 | 56 | l net.Listener 57 | mu sync.Mutex 58 | wg sync.WaitGroup 59 | doneChan chan struct{} 60 | handlers map[Enum]Handler 61 | } 62 | 63 | // Handler processes specific KMIP operation 64 | type Handler func(req *RequestContext, item *RequestBatchItem) (resp interface{}, err error) 65 | 66 | // SessionContext is initialized for each connection 67 | type SessionContext struct { 68 | // Unique session identificator 69 | SessionID string 70 | 71 | // Additional opaque data related to connection auth, as returned by Server.SessionAuthHandler 72 | SessionAuth interface{} 73 | } 74 | 75 | // RequestContext covers batch of requests 76 | type RequestContext struct { 77 | SessionContext 78 | 79 | // RequestAuth captures result of request authentication 80 | RequestAuth interface{} 81 | } 82 | 83 | // ListenAndServe creates TLS listening socket and calls Serve 84 | // 85 | // Channel initializedCh will be closed when listener is initialized 86 | // (or fails to be initialized) 87 | func (s *Server) ListenAndServe(initializedCh chan struct{}) error { 88 | addr := s.Addr 89 | if addr == "" { 90 | addr = ":5696" 91 | } 92 | 93 | l, err := tls.Listen("tcp", addr, s.TLSConfig) 94 | if err != nil { 95 | close(initializedCh) 96 | return err 97 | } 98 | 99 | return s.Serve(l, initializedCh) 100 | } 101 | 102 | // Serve starts accepting and serving KMIP connection on a given listener 103 | // 104 | // Channel initializedCh will be closed when listener is initialized 105 | // (or fails to be initialized) 106 | func (s *Server) Serve(l net.Listener, initializedCh chan struct{}) error { 107 | s.mu.Lock() 108 | s.l = l 109 | 110 | if s.Log == nil { 111 | s.Log = log.New(ioutil.Discard, "", log.LstdFlags) 112 | } 113 | 114 | if len(s.SupportedVersions) == 0 { 115 | s.SupportedVersions = append([]ProtocolVersion(nil), DefaultSupportedVersions...) 116 | } 117 | 118 | if s.handlers == nil { 119 | s.initHandlers() 120 | } 121 | s.mu.Unlock() 122 | 123 | close(initializedCh) 124 | 125 | defer l.Close() 126 | 127 | lastSession := uint32(0) 128 | 129 | var tempDelay time.Duration 130 | 131 | for { 132 | conn, err := l.Accept() 133 | if err != nil { 134 | select { 135 | case <-s.getDoneChan(): 136 | return nil 137 | default: 138 | } 139 | 140 | if netErr, ok := err.(net.Error); ok && netErr.Temporary() { 141 | if tempDelay == 0 { 142 | tempDelay = 5 * time.Millisecond 143 | } else { 144 | tempDelay *= 2 145 | } 146 | if max := 1 * time.Second; tempDelay > max { 147 | tempDelay = max 148 | } 149 | s.Log.Printf("[ERROR] Accept error: %s, retrying in %s", err, tempDelay) 150 | time.Sleep(tempDelay) 151 | continue 152 | } 153 | 154 | return err 155 | } 156 | 157 | lastSession++ 158 | tempDelay = 0 159 | 160 | s.wg.Add(1) 161 | go s.serve(conn, fmt.Sprintf("%08x", lastSession)) 162 | } 163 | } 164 | 165 | // Shutdown performs graceful shutdown of KMIP server waiting for connections to be closed 166 | // 167 | // Context might be used to limit time to wait for draining complete 168 | func (s *Server) Shutdown(ctx context.Context) error { 169 | close(s.getDoneChan()) 170 | 171 | s.mu.Lock() 172 | if s.l != nil { 173 | s.l.Close() 174 | s.l = nil 175 | } 176 | s.mu.Unlock() 177 | 178 | waitGroupDone := make(chan struct{}) 179 | 180 | go func() { 181 | s.wg.Wait() 182 | close(waitGroupDone) 183 | }() 184 | 185 | select { 186 | case <-ctx.Done(): 187 | return ctx.Err() 188 | case <-waitGroupDone: 189 | return nil 190 | } 191 | } 192 | 193 | // Handle register handler for operation 194 | // 195 | // Server provides default handler for DISCOVER_VERSIONS operation, any other 196 | // operation should be specifically enabled via Handle 197 | func (s *Server) Handle(operation Enum, handler Handler) { 198 | if s.handlers == nil { 199 | s.initHandlers() 200 | } 201 | 202 | s.handlers[operation] = handler 203 | } 204 | 205 | func (s *Server) initHandlers() { 206 | s.handlers = make(map[Enum]Handler) 207 | s.handlers[OPERATION_DISCOVER_VERSIONS] = s.handleDiscoverVersions 208 | } 209 | 210 | func (s *Server) getDoneChan() chan struct{} { 211 | s.mu.Lock() 212 | defer s.mu.Unlock() 213 | 214 | if s.doneChan == nil { 215 | s.doneChan = make(chan struct{}) 216 | } 217 | 218 | return s.doneChan 219 | } 220 | 221 | func (s *Server) serve(conn net.Conn, session string) { 222 | defer s.wg.Done() 223 | defer func() { 224 | s.Log.Printf("[INFO] [%s] Closed connection from %s", session, conn.RemoteAddr().String()) 225 | conn.Close() 226 | }() 227 | 228 | s.Log.Printf("[INFO] [%s] New connection from %s", session, conn.RemoteAddr().String()) 229 | 230 | sessionCtx := &SessionContext{ 231 | SessionID: session, 232 | } 233 | 234 | if tlsConn, ok := conn.(*tls.Conn); ok { 235 | if s.ReadTimeout != 0 { 236 | _ = conn.SetReadDeadline(time.Now().Add(s.ReadTimeout)) 237 | } 238 | if s.WriteTimeout != 0 { 239 | _ = conn.SetWriteDeadline(time.Now().Add(s.WriteTimeout)) 240 | } 241 | 242 | if err := tlsConn.Handshake(); err != nil { 243 | s.Log.Printf("[ERROR] [%s] Error in TLS handshake: %s", session, err) 244 | return 245 | } 246 | } 247 | 248 | s.mu.Lock() 249 | sessionAuthHandler := s.SessionAuthHandler 250 | s.mu.Unlock() 251 | 252 | if sessionAuthHandler != nil { 253 | var err error 254 | 255 | sessionCtx.SessionAuth, err = sessionAuthHandler(conn) 256 | if err != nil { 257 | s.Log.Printf("[ERROR] [%s] Error in session auth handler: %s", session, err) 258 | return 259 | } 260 | } 261 | 262 | d := NewDecoder(conn) 263 | e := NewEncoder(conn) 264 | 265 | for { 266 | var req = &Request{} 267 | 268 | if s.ReadTimeout != 0 { 269 | _ = conn.SetReadDeadline(time.Now().Add(s.ReadTimeout)) 270 | } 271 | 272 | err := d.Decode(req) 273 | if err == io.EOF { 274 | break 275 | } 276 | 277 | if err != nil { 278 | s.Log.Printf("[ERROR] [%s] Error decoding KMIP message: %s", session, err) 279 | break 280 | } 281 | 282 | var resp *Response 283 | resp, err = s.handleBatch(sessionCtx, req) 284 | if err != nil { 285 | s.Log.Printf("[ERROR] [%s] Fatal error handling batch: %s", session, err) 286 | break 287 | } 288 | 289 | if s.WriteTimeout != 0 { 290 | _ = conn.SetWriteDeadline(time.Now().Add(s.WriteTimeout)) 291 | } 292 | 293 | err = e.Encode(resp) 294 | if err != nil { 295 | s.Log.Printf("[ERROR] [%s] Error encoding KMIP response: %s", session, err) 296 | } 297 | } 298 | } 299 | 300 | func (s *Server) handleBatch(session *SessionContext, req *Request) (resp *Response, err error) { 301 | if int(req.Header.BatchCount) != len(req.BatchItems) { 302 | err = errors.Errorf("request batch count doesn't match number of batch items: %d != %d", req.Header.BatchCount, len(req.BatchItems)) 303 | return 304 | } 305 | 306 | if req.Header.AsynchronousIndicator { 307 | err = errors.New("asynchnronous requests are not supported") 308 | return 309 | } 310 | 311 | resp = &Response{ 312 | Header: ResponseHeader{ 313 | Version: req.Header.Version, 314 | TimeStamp: time.Now(), 315 | ClientCorrelationValue: req.Header.ClientCorrelationValue, 316 | BatchCount: req.Header.BatchCount, 317 | }, 318 | BatchItems: make([]ResponseBatchItem, req.Header.BatchCount), 319 | } 320 | 321 | requestCtx := &RequestContext{ 322 | SessionContext: *session, 323 | } 324 | 325 | if req.Header.Authentication.CredentialType != 0 { 326 | if s.RequestAuthHandler == nil { 327 | err = errors.New("request has authentication set, but no auth handler configured") 328 | return 329 | } 330 | requestCtx.RequestAuth, err = s.RequestAuthHandler(session, &req.Header.Authentication) 331 | if err != nil { 332 | err = errors.Wrap(err, "error running auth handler") 333 | return 334 | } 335 | } 336 | 337 | for i := range req.BatchItems { 338 | resp.BatchItems[i].Operation = req.BatchItems[i].Operation 339 | resp.BatchItems[i].UniqueID = append([]byte(nil), req.BatchItems[i].UniqueID...) 340 | 341 | var ( 342 | batchResp interface{} 343 | batchErr error 344 | ) 345 | 346 | batchResp, batchErr = s.handleWrapped(requestCtx, &req.BatchItems[i]) 347 | if batchErr != nil { 348 | s.Log.Printf("[WARN] [%s] Request failed, operation %v: %s", requestCtx.SessionID, operationMap[req.BatchItems[i].Operation], batchErr) 349 | 350 | resp.BatchItems[i].ResultStatus = RESULT_STATUS_OPERATION_FAILED 351 | // TODO: should we skip returning error message? or return it only for specific errors? 352 | resp.BatchItems[i].ResultMessage = batchErr.Error() 353 | if protoErr, ok := batchErr.(Error); ok { 354 | resp.BatchItems[i].ResultReason = protoErr.ResultReason() 355 | } else { 356 | resp.BatchItems[i].ResultReason = RESULT_REASON_GENERAL_FAILURE 357 | } 358 | } else { 359 | s.Log.Printf("[INFO] [%s] Request processed, operation %v", requestCtx.SessionID, operationMap[req.BatchItems[i].Operation]) 360 | resp.BatchItems[i].ResultStatus = RESULT_STATUS_SUCCESS 361 | resp.BatchItems[i].ResponsePayload = batchResp 362 | } 363 | } 364 | 365 | return 366 | } 367 | 368 | func (s *Server) handleWrapped(request *RequestContext, item *RequestBatchItem) (resp interface{}, err error) { 369 | defer func() { 370 | if p := recover(); p != nil { 371 | err = errors.Errorf("panic: %s", p) 372 | 373 | buf := make([]byte, 8192) 374 | 375 | n := runtime.Stack(buf, false) 376 | s.Log.Printf("[ERROR] [%s] Panic in request handler, operation %s: %s", request.SessionID, operationMap[item.Operation], string(buf[:n])) 377 | } 378 | }() 379 | 380 | handler := s.handlers[item.Operation] 381 | 382 | if handler == nil { 383 | err = wrapError(errors.New("operation not supported"), RESULT_REASON_OPERATION_NOT_SUPPORTED) 384 | return 385 | } 386 | 387 | resp, err = handler(request, item) 388 | return 389 | } 390 | 391 | func (s *Server) handleDiscoverVersions(req *RequestContext, item *RequestBatchItem) (resp interface{}, err error) { 392 | response := DiscoverVersionsResponse{} 393 | 394 | request, ok := item.RequestPayload.(DiscoverVersionsRequest) 395 | if !ok { 396 | err = wrapError(errors.New("wrong request body"), RESULT_REASON_INVALID_MESSAGE) 397 | return 398 | } 399 | 400 | if len(request.ProtocolVersions) == 0 { 401 | // return all the versions 402 | response.ProtocolVersions = append([]ProtocolVersion(nil), s.SupportedVersions...) 403 | } else { 404 | // find matching versions 405 | for _, version := range request.ProtocolVersions { 406 | for _, v := range s.SupportedVersions { 407 | if version == v { 408 | response.ProtocolVersions = append(response.ProtocolVersions, v) 409 | break 410 | } 411 | } 412 | } 413 | } 414 | 415 | resp = response 416 | return 417 | } 418 | 419 | // DefaultSupportedVersions is a default list of supported KMIP versions 420 | var DefaultSupportedVersions = []ProtocolVersion{ 421 | {Major: 1, Minor: 4}, 422 | {Major: 1, Minor: 3}, 423 | {Major: 1, Minor: 2}, 424 | {Major: 1, Minor: 1}, 425 | } 426 | -------------------------------------------------------------------------------- /server_test.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "context" 9 | "crypto/tls" 10 | "crypto/x509" 11 | "log" 12 | "net" 13 | "os" 14 | "testing" 15 | "time" 16 | 17 | "github.com/pkg/errors" 18 | "github.com/stretchr/testify/suite" 19 | ) 20 | 21 | type ServerSuite struct { 22 | suite.Suite 23 | 24 | certs CertificateSet 25 | server Server 26 | client Client 27 | 28 | listenCh chan error 29 | } 30 | 31 | func (s *ServerSuite) SetupSuite() { 32 | s.Require().NoError(s.certs.Generate([]string{"localhost"}, []net.IP{net.IPv4(127, 0, 0, 1)})) 33 | 34 | s.server.Addr = "localhost:" 35 | s.server.TLSConfig = &tls.Config{} //nolint:gosec 36 | DefaultServerTLSConfig(s.server.TLSConfig) 37 | s.server.TLSConfig.ClientCAs = s.certs.CAPool 38 | s.server.TLSConfig.Certificates = []tls.Certificate{ 39 | { 40 | Certificate: [][]byte{s.certs.ServerCert.Raw}, 41 | PrivateKey: s.certs.ServerKey, 42 | }, 43 | } 44 | 45 | s.server.ReadTimeout = time.Second 46 | s.server.WriteTimeout = time.Second 47 | 48 | s.server.Log = log.New(os.Stderr, "[kmip] ", log.LstdFlags) 49 | 50 | s.listenCh = make(chan error, 1) 51 | initializedCh := make(chan struct{}) 52 | 53 | go func() { 54 | s.listenCh <- s.server.ListenAndServe(initializedCh) 55 | }() 56 | 57 | <-initializedCh 58 | } 59 | 60 | func (s *ServerSuite) SetupTest() { 61 | s.server.mu.Lock() 62 | addr := s.server.l.Addr().String() 63 | s.server.mu.Unlock() 64 | 65 | _, port, err := net.SplitHostPort(addr) 66 | s.Require().NoError(err) 67 | 68 | s.client.Endpoint = "localhost:" + port 69 | s.client.TLSConfig = &tls.Config{} //nolint:gosec 70 | DefaultClientTLSConfig(s.client.TLSConfig) 71 | s.client.TLSConfig.RootCAs = s.certs.CAPool 72 | s.client.TLSConfig.Certificates = []tls.Certificate{ 73 | { 74 | Certificate: [][]byte{s.certs.ClientCert.Raw}, 75 | PrivateKey: s.certs.ClientKey, 76 | }, 77 | } 78 | 79 | s.client.ReadTimeout = time.Second 80 | s.client.WriteTimeout = time.Second 81 | } 82 | 83 | func (s *ServerSuite) TearDownTest() { 84 | s.Require().NoError(s.client.Close()) 85 | 86 | // reset server state 87 | s.server.mu.Lock() 88 | s.server.SessionAuthHandler = nil 89 | s.server.initHandlers() 90 | s.server.mu.Unlock() 91 | } 92 | 93 | func (s *ServerSuite) TearDownSuite() { 94 | ctx, ctxCancel := context.WithTimeout(context.Background(), time.Second) 95 | defer ctxCancel() 96 | 97 | s.Require().NoError(s.server.Shutdown(ctx)) 98 | s.Require().NoError(<-s.listenCh) 99 | } 100 | 101 | func (s *ServerSuite) TestDiscoverVersions() { 102 | s.Require().NoError(s.client.Connect()) 103 | 104 | versions, err := s.client.DiscoverVersions(DefaultSupportedVersions) 105 | s.Require().NoError(err) 106 | s.Require().Equal(DefaultSupportedVersions, versions) 107 | 108 | versions, err = s.client.DiscoverVersions(nil) 109 | s.Require().NoError(err) 110 | s.Require().Equal(DefaultSupportedVersions, versions) 111 | 112 | versions, err = s.client.DiscoverVersions([]ProtocolVersion{{Major: 1, Minor: 2}}) 113 | s.Require().NoError(err) 114 | s.Require().Equal([]ProtocolVersion{{Major: 1, Minor: 2}}, versions) 115 | 116 | versions, err = s.client.DiscoverVersions([]ProtocolVersion{{Major: 2, Minor: 0}}) 117 | s.Require().NoError(err) 118 | s.Require().Equal([]ProtocolVersion(nil), versions) 119 | } 120 | 121 | func (s *ServerSuite) TestSessionAuthHandlerOkay() { 122 | s.server.SessionAuthHandler = func(conn net.Conn) (interface{}, error) { 123 | commonName := conn.(*tls.Conn).ConnectionState().PeerCertificates[0].Subject.CommonName 124 | 125 | if commonName != "client_auth_test_cert" { 126 | return nil, errors.New("wrong common name") 127 | } 128 | 129 | return commonName, nil 130 | } 131 | 132 | s.server.Handle(OPERATION_DISCOVER_VERSIONS, func(req *RequestContext, item *RequestBatchItem) (interface{}, error) { 133 | if req.SessionAuth.(string) != "client_auth_test_cert" { 134 | return nil, errors.New("wrong session auth") 135 | } 136 | 137 | return DiscoverVersionsResponse{ 138 | ProtocolVersions: nil, 139 | }, nil 140 | }) 141 | 142 | s.Require().NoError(s.client.Connect()) 143 | 144 | versions, err := s.client.DiscoverVersions(nil) 145 | s.Require().NoError(err) 146 | s.Require().Equal([]ProtocolVersion(nil), versions) 147 | } 148 | 149 | func (s *ServerSuite) TestSessionAuthHandlerFail() { 150 | s.server.SessionAuthHandler = func(conn net.Conn) (interface{}, error) { 151 | commonName := conn.(*tls.Conn).ConnectionState().PeerCertificates[0].Subject.CommonName 152 | 153 | if commonName != "xxx" { 154 | return nil, errors.New("wrong common name") 155 | } 156 | 157 | return commonName, nil 158 | } 159 | 160 | s.Require().NoError(s.client.Connect()) 161 | 162 | _, err := s.client.DiscoverVersions(nil) 163 | s.Require().Regexp("(broken pipe|EOF)$", errors.Cause(err).Error()) 164 | 165 | s.client.Close() 166 | } 167 | 168 | func (s *ServerSuite) TestConnectTLSNoCert() { 169 | var savedCerts []tls.Certificate 170 | savedCerts, s.client.TLSConfig.Certificates = s.client.TLSConfig.Certificates, nil 171 | defer func() { 172 | s.client.TLSConfig.Certificates = savedCerts 173 | }() 174 | 175 | err := s.client.Connect() 176 | if err != nil { 177 | s.Require().EqualError(errors.Cause(err), "remote error: tls: bad certificate") 178 | } else { 179 | _, err = s.client.DiscoverVersions(nil) 180 | 181 | s.Require().Error(err) 182 | } 183 | 184 | s.client.Close() //nolint:errcheck 185 | } 186 | 187 | func (s *ServerSuite) TestConnectTLSNoCA() { 188 | var savedPool *x509.CertPool 189 | savedPool, s.client.TLSConfig.RootCAs = s.client.TLSConfig.RootCAs, nil 190 | defer func() { 191 | s.client.TLSConfig.RootCAs = savedPool 192 | }() 193 | 194 | s.Require().EqualError(errors.Cause(s.client.Connect()), "x509: certificate signed by unknown authority") 195 | } 196 | 197 | func (s *ServerSuite) TestOperationGenericFail() { 198 | s.server.Handle(OPERATION_DISCOVER_VERSIONS, func(req *RequestContext, item *RequestBatchItem) (interface{}, error) { 199 | return nil, errors.New("oops!") 200 | }) 201 | 202 | s.Require().NoError(s.client.Connect()) 203 | 204 | _, err := s.client.DiscoverVersions(nil) 205 | s.Require().EqualError(errors.Cause(err), "oops!") 206 | s.Require().Equal(errors.Cause(err).(Error).ResultReason(), RESULT_REASON_GENERAL_FAILURE) 207 | } 208 | 209 | func (s *ServerSuite) TestOperationPanic() { 210 | s.server.Handle(OPERATION_DISCOVER_VERSIONS, func(req *RequestContext, item *RequestBatchItem) (interface{}, error) { 211 | panic("oops!") 212 | }) 213 | 214 | s.Require().NoError(s.client.Connect()) 215 | 216 | _, err := s.client.DiscoverVersions(nil) 217 | s.Require().EqualError(errors.Cause(err), "panic: oops!") 218 | s.Require().Equal(errors.Cause(err).(Error).ResultReason(), RESULT_REASON_GENERAL_FAILURE) 219 | } 220 | 221 | func (s *ServerSuite) TestOperationFailWithReason() { 222 | s.server.Handle(OPERATION_DISCOVER_VERSIONS, func(req *RequestContext, item *RequestBatchItem) (interface{}, error) { 223 | return nil, wrapError(errors.New("oops!"), RESULT_REASON_CRYPTOGRAPHIC_FAILURE) 224 | }) 225 | 226 | s.Require().NoError(s.client.Connect()) 227 | 228 | _, err := s.client.DiscoverVersions(nil) 229 | s.Require().EqualError(errors.Cause(err), "oops!") 230 | s.Require().Equal(errors.Cause(err).(Error).ResultReason(), RESULT_REASON_CRYPTOGRAPHIC_FAILURE) 231 | } 232 | 233 | func (s *ServerSuite) TestOperationNotSupported() { 234 | s.Require().NoError(s.client.Connect()) 235 | 236 | _, err := s.client.Send(OPERATION_GET, GetRequest{}) 237 | s.Require().EqualError(errors.Cause(err), "operation not supported") 238 | s.Require().Equal(errors.Cause(err).(Error).ResultReason(), RESULT_REASON_OPERATION_NOT_SUPPORTED) 239 | } 240 | 241 | func TestServerSuite(t *testing.T) { 242 | suite.Run(t, new(ServerSuite)) 243 | } 244 | -------------------------------------------------------------------------------- /tls.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | import "crypto/tls" 4 | 5 | /* This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | 9 | // DefaultServerTLSConfig fills in good defaults for server TLS configuration 10 | func DefaultServerTLSConfig(config *tls.Config) { 11 | config.MinVersion = tls.VersionTLS12 12 | config.PreferServerCipherSuites = true 13 | config.ClientAuth = tls.RequireAndVerifyClientCert 14 | } 15 | 16 | // DefaultClientTLSConfig fills in good defaults for client TLS configuration 17 | func DefaultClientTLSConfig(config *tls.Config) { 18 | config.MinVersion = tls.VersionTLS12 19 | } 20 | -------------------------------------------------------------------------------- /tls_test.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "crypto/ecdsa" 9 | "crypto/elliptic" 10 | "crypto/rand" 11 | "crypto/x509" 12 | "crypto/x509/pkix" 13 | "math/big" 14 | "net" 15 | "time" 16 | 17 | "github.com/pkg/errors" 18 | ) 19 | 20 | type CertificateSet struct { 21 | CAKey *ecdsa.PrivateKey 22 | CACert *x509.Certificate 23 | 24 | ServerKey *ecdsa.PrivateKey 25 | ServerCert *x509.Certificate 26 | 27 | ClientKey *ecdsa.PrivateKey 28 | ClientCert *x509.Certificate 29 | 30 | CAPool *x509.CertPool 31 | } 32 | 33 | func (set *CertificateSet) Generate(hostnames []string, ips []net.IP) error { 34 | notBefore := time.Now() 35 | notAfter := notBefore.Add(time.Hour) 36 | 37 | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 38 | serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 39 | if err != nil { 40 | return errors.Wrapf(err, "failed to generate serial number") 41 | } 42 | 43 | set.CAKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 44 | if err != nil { 45 | return errors.Wrapf(err, "failt to generate CA key") 46 | } 47 | 48 | rootTemplate := x509.Certificate{ 49 | SerialNumber: serialNumber, 50 | Subject: pkix.Name{ 51 | Organization: []string{"Acme Co"}, 52 | CommonName: "Root CA", 53 | }, 54 | NotBefore: notBefore, 55 | NotAfter: notAfter, 56 | KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, 57 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, 58 | BasicConstraintsValid: true, 59 | IsCA: true, 60 | } 61 | 62 | derBytes, err := x509.CreateCertificate(rand.Reader, &rootTemplate, &rootTemplate, &set.CAKey.PublicKey, set.CAKey) 63 | if err != nil { 64 | return errors.Wrapf(err, "error generating CA certificate") 65 | } 66 | 67 | set.CACert, err = x509.ParseCertificate(derBytes) 68 | if err != nil { 69 | return errors.Wrapf(err, "error parsing CA cert") 70 | } 71 | 72 | set.ServerKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 73 | if err != nil { 74 | return errors.Wrapf(err, "error generating server key") 75 | } 76 | 77 | serialNumber, err = rand.Int(rand.Reader, serialNumberLimit) 78 | if err != nil { 79 | return errors.Wrapf(err, "failed to generate serial number") 80 | } 81 | 82 | serverTemplate := x509.Certificate{ 83 | SerialNumber: serialNumber, 84 | Subject: pkix.Name{ 85 | Organization: []string{"Acme Co"}, 86 | CommonName: "test_cert_1", 87 | }, 88 | NotBefore: notBefore, 89 | NotAfter: notAfter, 90 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, 91 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 92 | BasicConstraintsValid: true, 93 | IsCA: false, 94 | IPAddresses: ips, 95 | DNSNames: hostnames, 96 | } 97 | 98 | derBytes, err = x509.CreateCertificate(rand.Reader, &serverTemplate, &rootTemplate, &set.ServerKey.PublicKey, set.CAKey) 99 | if err != nil { 100 | return errors.Wrapf(err, "error generating server cert") 101 | } 102 | 103 | set.ServerCert, err = x509.ParseCertificate(derBytes) 104 | if err != nil { 105 | return errors.Wrapf(err, "error parsing server cert") 106 | } 107 | 108 | set.ClientKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 109 | if err != nil { 110 | return errors.Wrapf(err, "error generating client key") 111 | } 112 | 113 | clientTemplate := x509.Certificate{ 114 | SerialNumber: new(big.Int).SetInt64(4), 115 | Subject: pkix.Name{ 116 | Organization: []string{"Acme Co"}, 117 | CommonName: "client_auth_test_cert", 118 | }, 119 | NotBefore: notBefore, 120 | NotAfter: notAfter, 121 | KeyUsage: x509.KeyUsageDigitalSignature, 122 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 123 | BasicConstraintsValid: true, 124 | IsCA: false, 125 | } 126 | 127 | derBytes, err = x509.CreateCertificate(rand.Reader, &clientTemplate, &rootTemplate, &set.ClientKey.PublicKey, set.CAKey) 128 | if err != nil { 129 | return errors.Wrapf(err, "error generating client cert") 130 | } 131 | 132 | set.ClientCert, err = x509.ParseCertificate(derBytes) 133 | if err != nil { 134 | return errors.Wrapf(err, "error parsing client cert") 135 | } 136 | 137 | set.CAPool = x509.NewCertPool() 138 | set.CAPool.AddCert(set.CACert) 139 | 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | package kmip 2 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | import ( 8 | "reflect" 9 | "time" 10 | ) 11 | 12 | // Tag is a number that designates the specific Protocol Field or Object that the TTLV object represents 13 | type Tag uint32 14 | 15 | // Type is a byte containing a coded value that indicates the data type of the data object 16 | type Type uint8 17 | 18 | // Enum is KMIP Enumeration type 19 | type Enum uint32 20 | 21 | // DynamicDispatch is an interface for structure go set field value based on other field values 22 | type DynamicDispatch interface { 23 | BuildFieldValue(name string) (interface{}, error) 24 | } 25 | 26 | var ( 27 | typeOfTag = reflect.TypeOf(Tag(0)) 28 | typeOfEnum = reflect.TypeOf(Enum(0)) 29 | typeOfInt32 = reflect.TypeOf(int32(0)) 30 | typeOfInt64 = reflect.TypeOf(int64(0)) 31 | typeOfBool = reflect.TypeOf(false) 32 | typeOfBytes = reflect.TypeOf([]byte(nil)) 33 | typeOfString = reflect.TypeOf("") 34 | typeOfTime = reflect.TypeOf(time.Time{}) 35 | typeOfDuration = reflect.TypeOf(time.Duration(0)) 36 | ) 37 | --------------------------------------------------------------------------------