ciphers_gcm.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright (C) 2017. See AUTHORS.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package openssl
  15. // #include <openssl/evp.h>
  16. import "C"
  17. import (
  18. "errors"
  19. "fmt"
  20. )
  21. type AuthenticatedEncryptionCipherCtx interface {
  22. EncryptionCipherCtx
  23. // data passed in to ExtraData() is part of the final output; it is
  24. // not encrypted itself, but is part of the authenticated data. when
  25. // decrypting or authenticating, pass back with the decryption
  26. // context's ExtraData()
  27. ExtraData([]byte) error
  28. // use after finalizing encryption to get the authenticating tag
  29. GetTag() ([]byte, error)
  30. }
  31. type AuthenticatedDecryptionCipherCtx interface {
  32. DecryptionCipherCtx
  33. // pass in any extra data that was added during encryption with the
  34. // encryption context's ExtraData()
  35. ExtraData([]byte) error
  36. // use before finalizing decryption to tell the library what the
  37. // tag is expected to be
  38. SetTag([]byte) error
  39. }
  40. type authEncryptionCipherCtx struct {
  41. *encryptionCipherCtx
  42. }
  43. type authDecryptionCipherCtx struct {
  44. *decryptionCipherCtx
  45. }
  46. func getGCMCipher(blocksize int) (*Cipher, error) {
  47. var cipherptr *C.EVP_CIPHER
  48. switch blocksize {
  49. case 256:
  50. cipherptr = C.EVP_aes_256_gcm()
  51. case 192:
  52. cipherptr = C.EVP_aes_192_gcm()
  53. case 128:
  54. cipherptr = C.EVP_aes_128_gcm()
  55. default:
  56. return nil, fmt.Errorf("unknown block size %d", blocksize)
  57. }
  58. return &Cipher{ptr: cipherptr}, nil
  59. }
  60. func NewGCMEncryptionCipherCtx(blocksize int, e *Engine, key, iv []byte) (
  61. AuthenticatedEncryptionCipherCtx, error) {
  62. cipher, err := getGCMCipher(blocksize)
  63. if err != nil {
  64. return nil, err
  65. }
  66. ctx, err := newEncryptionCipherCtx(cipher, e, key, nil)
  67. if err != nil {
  68. return nil, err
  69. }
  70. if len(iv) > 0 {
  71. err := ctx.setCtrl(C.EVP_CTRL_GCM_SET_IVLEN, len(iv))
  72. if err != nil {
  73. return nil, fmt.Errorf("could not set IV len to %d: %s",
  74. len(iv), err)
  75. }
  76. if 1 != C.EVP_EncryptInit_ex(ctx.ctx, nil, nil, nil,
  77. (*C.uchar)(&iv[0])) {
  78. return nil, errors.New("failed to apply IV")
  79. }
  80. }
  81. return &authEncryptionCipherCtx{encryptionCipherCtx: ctx}, nil
  82. }
  83. func NewGCMDecryptionCipherCtx(blocksize int, e *Engine, key, iv []byte) (
  84. AuthenticatedDecryptionCipherCtx, error) {
  85. cipher, err := getGCMCipher(blocksize)
  86. if err != nil {
  87. return nil, err
  88. }
  89. ctx, err := newDecryptionCipherCtx(cipher, e, key, nil)
  90. if err != nil {
  91. return nil, err
  92. }
  93. if len(iv) > 0 {
  94. err := ctx.setCtrl(C.EVP_CTRL_GCM_SET_IVLEN, len(iv))
  95. if err != nil {
  96. return nil, fmt.Errorf("could not set IV len to %d: %s",
  97. len(iv), err)
  98. }
  99. if 1 != C.EVP_DecryptInit_ex(ctx.ctx, nil, nil, nil,
  100. (*C.uchar)(&iv[0])) {
  101. return nil, errors.New("failed to apply IV")
  102. }
  103. }
  104. return &authDecryptionCipherCtx{decryptionCipherCtx: ctx}, nil
  105. }
  106. func (ctx *authEncryptionCipherCtx) ExtraData(aad []byte) error {
  107. if aad == nil {
  108. return nil
  109. }
  110. var outlen C.int
  111. if 1 != C.EVP_EncryptUpdate(ctx.ctx, nil, &outlen, (*C.uchar)(&aad[0]),
  112. C.int(len(aad))) {
  113. return errors.New("failed to add additional authenticated data")
  114. }
  115. return nil
  116. }
  117. func (ctx *authDecryptionCipherCtx) ExtraData(aad []byte) error {
  118. if aad == nil {
  119. return nil
  120. }
  121. var outlen C.int
  122. if 1 != C.EVP_DecryptUpdate(ctx.ctx, nil, &outlen, (*C.uchar)(&aad[0]),
  123. C.int(len(aad))) {
  124. return errors.New("failed to add additional authenticated data")
  125. }
  126. return nil
  127. }
  128. func (ctx *authEncryptionCipherCtx) GetTag() ([]byte, error) {
  129. return ctx.getCtrlBytes(C.EVP_CTRL_GCM_GET_TAG, GCM_TAG_MAXLEN,
  130. GCM_TAG_MAXLEN)
  131. }
  132. func (ctx *authDecryptionCipherCtx) SetTag(tag []byte) error {
  133. return ctx.setCtrlBytes(C.EVP_CTRL_GCM_SET_TAG, len(tag), tag)
  134. }