Blame vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go

Packit 63bb0d
// Copyright 2015 The Go Authors. All rights reserved.
Packit 63bb0d
// Use of this source code is governed by a BSD-style
Packit 63bb0d
// license that can be found in the LICENSE file.
Packit 63bb0d
Packit 63bb0d
// Package rc2 implements the RC2 cipher
Packit 63bb0d
/*
Packit 63bb0d
https://www.ietf.org/rfc/rfc2268.txt
Packit 63bb0d
http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf
Packit 63bb0d
Packit 63bb0d
This code is licensed under the MIT license.
Packit 63bb0d
*/
Packit 63bb0d
package rc2
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"crypto/cipher"
Packit 63bb0d
	"encoding/binary"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// The rc2 block size in bytes
Packit 63bb0d
const BlockSize = 8
Packit 63bb0d
Packit 63bb0d
type rc2Cipher struct {
Packit 63bb0d
	k [64]uint16
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// New returns a new rc2 cipher with the given key and effective key length t1
Packit 63bb0d
func New(key []byte, t1 int) (cipher.Block, error) {
Packit 63bb0d
	// TODO(dgryski): error checking for key length
Packit 63bb0d
	return &rc2Cipher{
Packit 63bb0d
		k: expandKey(key, t1),
Packit 63bb0d
	}, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (*rc2Cipher) BlockSize() int { return BlockSize }
Packit 63bb0d
Packit 63bb0d
var piTable = [256]byte{
Packit 63bb0d
	0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
Packit 63bb0d
	0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
Packit 63bb0d
	0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
Packit 63bb0d
	0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
Packit 63bb0d
	0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
Packit 63bb0d
	0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
Packit 63bb0d
	0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
Packit 63bb0d
	0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
Packit 63bb0d
	0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
Packit 63bb0d
	0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
Packit 63bb0d
	0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
Packit 63bb0d
	0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
Packit 63bb0d
	0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
Packit 63bb0d
	0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
Packit 63bb0d
	0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
Packit 63bb0d
	0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad,
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func expandKey(key []byte, t1 int) [64]uint16 {
Packit 63bb0d
Packit 63bb0d
	l := make([]byte, 128)
Packit 63bb0d
	copy(l, key)
Packit 63bb0d
Packit 63bb0d
	var t = len(key)
Packit 63bb0d
	var t8 = (t1 + 7) / 8
Packit 63bb0d
	var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8))))
Packit 63bb0d
Packit 63bb0d
	for i := len(key); i < 128; i++ {
Packit 63bb0d
		l[i] = piTable[l[i-1]+l[uint8(i-t)]]
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	l[128-t8] = piTable[l[128-t8]&tm]
Packit 63bb0d
Packit 63bb0d
	for i := 127 - t8; i >= 0; i-- {
Packit 63bb0d
		l[i] = piTable[l[i+1]^l[i+t8]]
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var k [64]uint16
Packit 63bb0d
Packit 63bb0d
	for i := range k {
Packit 63bb0d
		k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return k
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func rotl16(x uint16, b uint) uint16 {
Packit 63bb0d
	return (x >> (16 - b)) | (x << b)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *rc2Cipher) Encrypt(dst, src []byte) {
Packit 63bb0d
Packit 63bb0d
	r0 := binary.LittleEndian.Uint16(src[0:])
Packit 63bb0d
	r1 := binary.LittleEndian.Uint16(src[2:])
Packit 63bb0d
	r2 := binary.LittleEndian.Uint16(src[4:])
Packit 63bb0d
	r3 := binary.LittleEndian.Uint16(src[6:])
Packit 63bb0d
Packit 63bb0d
	var j int
Packit 63bb0d
Packit 63bb0d
	for j <= 16 {
Packit 63bb0d
		// mix r0
Packit 63bb0d
		r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
Packit 63bb0d
		r0 = rotl16(r0, 1)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r1
Packit 63bb0d
		r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
Packit 63bb0d
		r1 = rotl16(r1, 2)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r2
Packit 63bb0d
		r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
Packit 63bb0d
		r2 = rotl16(r2, 3)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r3
Packit 63bb0d
		r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
Packit 63bb0d
		r3 = rotl16(r3, 5)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	r0 = r0 + c.k[r3&63]
Packit 63bb0d
	r1 = r1 + c.k[r0&63]
Packit 63bb0d
	r2 = r2 + c.k[r1&63]
Packit 63bb0d
	r3 = r3 + c.k[r2&63]
Packit 63bb0d
Packit 63bb0d
	for j <= 40 {
Packit 63bb0d
		// mix r0
Packit 63bb0d
		r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
Packit 63bb0d
		r0 = rotl16(r0, 1)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r1
Packit 63bb0d
		r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
Packit 63bb0d
		r1 = rotl16(r1, 2)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r2
Packit 63bb0d
		r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
Packit 63bb0d
		r2 = rotl16(r2, 3)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r3
Packit 63bb0d
		r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
Packit 63bb0d
		r3 = rotl16(r3, 5)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	r0 = r0 + c.k[r3&63]
Packit 63bb0d
	r1 = r1 + c.k[r0&63]
Packit 63bb0d
	r2 = r2 + c.k[r1&63]
Packit 63bb0d
	r3 = r3 + c.k[r2&63]
Packit 63bb0d
Packit 63bb0d
	for j <= 60 {
Packit 63bb0d
		// mix r0
Packit 63bb0d
		r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
Packit 63bb0d
		r0 = rotl16(r0, 1)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r1
Packit 63bb0d
		r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
Packit 63bb0d
		r1 = rotl16(r1, 2)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r2
Packit 63bb0d
		r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
Packit 63bb0d
		r2 = rotl16(r2, 3)
Packit 63bb0d
		j++
Packit 63bb0d
Packit 63bb0d
		// mix r3
Packit 63bb0d
		r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
Packit 63bb0d
		r3 = rotl16(r3, 5)
Packit 63bb0d
		j++
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[0:], r0)
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[2:], r1)
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[4:], r2)
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[6:], r3)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *rc2Cipher) Decrypt(dst, src []byte) {
Packit 63bb0d
Packit 63bb0d
	r0 := binary.LittleEndian.Uint16(src[0:])
Packit 63bb0d
	r1 := binary.LittleEndian.Uint16(src[2:])
Packit 63bb0d
	r2 := binary.LittleEndian.Uint16(src[4:])
Packit 63bb0d
	r3 := binary.LittleEndian.Uint16(src[6:])
Packit 63bb0d
Packit 63bb0d
	j := 63
Packit 63bb0d
Packit 63bb0d
	for j >= 44 {
Packit 63bb0d
		// unmix r3
Packit 63bb0d
		r3 = rotl16(r3, 16-5)
Packit 63bb0d
		r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r2
Packit 63bb0d
		r2 = rotl16(r2, 16-3)
Packit 63bb0d
		r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r1
Packit 63bb0d
		r1 = rotl16(r1, 16-2)
Packit 63bb0d
		r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r0
Packit 63bb0d
		r0 = rotl16(r0, 16-1)
Packit 63bb0d
		r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
Packit 63bb0d
		j--
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	r3 = r3 - c.k[r2&63]
Packit 63bb0d
	r2 = r2 - c.k[r1&63]
Packit 63bb0d
	r1 = r1 - c.k[r0&63]
Packit 63bb0d
	r0 = r0 - c.k[r3&63]
Packit 63bb0d
Packit 63bb0d
	for j >= 20 {
Packit 63bb0d
		// unmix r3
Packit 63bb0d
		r3 = rotl16(r3, 16-5)
Packit 63bb0d
		r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r2
Packit 63bb0d
		r2 = rotl16(r2, 16-3)
Packit 63bb0d
		r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r1
Packit 63bb0d
		r1 = rotl16(r1, 16-2)
Packit 63bb0d
		r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r0
Packit 63bb0d
		r0 = rotl16(r0, 16-1)
Packit 63bb0d
		r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	r3 = r3 - c.k[r2&63]
Packit 63bb0d
	r2 = r2 - c.k[r1&63]
Packit 63bb0d
	r1 = r1 - c.k[r0&63]
Packit 63bb0d
	r0 = r0 - c.k[r3&63]
Packit 63bb0d
Packit 63bb0d
	for j >= 0 {
Packit 63bb0d
		// unmix r3
Packit 63bb0d
		r3 = rotl16(r3, 16-5)
Packit 63bb0d
		r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r2
Packit 63bb0d
		r2 = rotl16(r2, 16-3)
Packit 63bb0d
		r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r1
Packit 63bb0d
		r1 = rotl16(r1, 16-2)
Packit 63bb0d
		r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
		// unmix r0
Packit 63bb0d
		r0 = rotl16(r0, 16-1)
Packit 63bb0d
		r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
Packit 63bb0d
		j--
Packit 63bb0d
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[0:], r0)
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[2:], r1)
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[4:], r2)
Packit 63bb0d
	binary.LittleEndian.PutUint16(dst[6:], r3)
Packit 63bb0d
}