hmac.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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 "shim.h"
  16. import "C"
  17. import (
  18. "errors"
  19. "runtime"
  20. "unsafe"
  21. )
  22. type HMAC struct {
  23. ctx *C.HMAC_CTX
  24. engine *Engine
  25. md *C.EVP_MD
  26. }
  27. func NewHMAC(key []byte, digestAlgorithm EVP_MD) (*HMAC, error) {
  28. return NewHMACWithEngine(key, digestAlgorithm, nil)
  29. }
  30. func NewHMACWithEngine(key []byte, digestAlgorithm EVP_MD, e *Engine) (*HMAC, error) {
  31. var md *C.EVP_MD = getDigestFunction(digestAlgorithm)
  32. h := &HMAC{engine: e, md: md}
  33. h.ctx = C.X_HMAC_CTX_new()
  34. if h.ctx == nil {
  35. return nil, errors.New("unable to allocate HMAC_CTX")
  36. }
  37. var c_e *C.ENGINE
  38. if e != nil {
  39. c_e = e.e
  40. }
  41. if rc := C.X_HMAC_Init_ex(h.ctx,
  42. unsafe.Pointer(&key[0]),
  43. C.int(len(key)),
  44. md,
  45. c_e); rc != 1 {
  46. C.X_HMAC_CTX_free(h.ctx)
  47. return nil, errors.New("failed to initialize HMAC_CTX")
  48. }
  49. runtime.SetFinalizer(h, func(h *HMAC) { h.Close() })
  50. return h, nil
  51. }
  52. func (h *HMAC) Close() {
  53. C.X_HMAC_CTX_free(h.ctx)
  54. }
  55. func (h *HMAC) Write(data []byte) (n int, err error) {
  56. if len(data) == 0 {
  57. return 0, nil
  58. }
  59. if rc := C.X_HMAC_Update(h.ctx, (*C.uchar)(unsafe.Pointer(&data[0])),
  60. C.size_t(len(data))); rc != 1 {
  61. return 0, errors.New("failed to update HMAC")
  62. }
  63. return len(data), nil
  64. }
  65. func (h *HMAC) Reset() error {
  66. if 1 != C.X_HMAC_Init_ex(h.ctx, nil, 0, nil, nil) {
  67. return errors.New("failed to reset HMAC_CTX")
  68. }
  69. return nil
  70. }
  71. func (h *HMAC) Final() (result []byte, err error) {
  72. mdLength := C.X_EVP_MD_size(h.md)
  73. result = make([]byte, mdLength)
  74. if rc := C.X_HMAC_Final(h.ctx, (*C.uchar)(unsafe.Pointer(&result[0])),
  75. (*C.uint)(unsafe.Pointer(&mdLength))); rc != 1 {
  76. return nil, errors.New("failed to finalized HMAC")
  77. }
  78. return result, h.Reset()
  79. }