func NewRoom( ctx scope.Context, kms security.KMS, private bool, name, version string, managers ...proto.Account) ( proto.ManagedRoom, error) { sec, err := proto.NewRoomSecurity(kms, name) if err != nil { return nil, err } managerKey := sec.KeyEncryptingKey.Clone() if err := kms.DecryptKey(&managerKey); err != nil { return nil, err } roomKeyPair, err := sec.Unlock(&managerKey) if err != nil { return nil, err } room := &memRoom{ RoomBase: RoomBase{ name: name, version: version, log: newMemLog(), agentBans: map[proto.UserID]time.Time{}, ipBans: map[string]time.Time{}, }, sec: sec, managerKey: &roomManagerKey{ RoomSecurity: sec, GrantManager: &proto.GrantManager{ Capabilities: &capabilities{}, KeyEncryptingKey: &sec.KeyEncryptingKey, SubjectKeyPair: &sec.KeyPair, SubjectNonce: sec.Nonce, }, }, } room.managerKey.GrantManager.Managers = room.managerKey var ( roomMsgKey proto.RoomMessageKey msgKey security.ManagedKey ) if private { roomMsgKey, err = room.GenerateMessageKey(ctx, kms) if err != nil { return nil, err } msgKey = roomMsgKey.ManagedKey() if err := kms.DecryptKey(&msgKey); err != nil { return nil, err } } for _, manager := range managers { kp := manager.KeyPair() c, err := security.GrantPublicKeyCapability( kms, sec.Nonce, roomKeyPair, &kp, nil, managerKey.Plaintext) if err != nil { return nil, err } room.managerKey.Capabilities.Save(ctx, manager, c) if private { c, err = security.GrantPublicKeyCapability( kms, roomMsgKey.Nonce(), roomKeyPair, &kp, nil, msgKey.Plaintext) if err != nil { return nil, err } room.messageKey.Capabilities.Save(ctx, manager, c) } } return room, nil }
func (b *Backend) CreateRoom( ctx scope.Context, kms security.KMS, private bool, name string, managers ...proto.Account) ( proto.ManagedRoom, error) { sec, err := proto.NewRoomSecurity(kms, name) if err != nil { return nil, err } logging.Logger(ctx).Printf("creating room: %s", name) room := &Room{ Name: name, IV: sec.KeyPair.IV, MAC: sec.MAC, Nonce: sec.Nonce, EncryptedManagementKey: sec.KeyEncryptingKey.Ciphertext, EncryptedPrivateKey: sec.KeyPair.EncryptedPrivateKey, PublicKey: sec.KeyPair.PublicKey, } var ( rmkb *RoomMessageKeyBinding msgKey security.ManagedKey ) if private { rmkb, err = room.generateMessageKey(b, kms) if err != nil { return nil, err } msgKey = rmkb.ManagedKey() if err := kms.DecryptKey(&msgKey); err != nil { return nil, err } } // Generate manager capabilities. managerKey := sec.KeyEncryptingKey.Clone() if err := kms.DecryptKey(&managerKey); err != nil { return nil, fmt.Errorf("manager key decrypt error: %s", err) } roomKeyPair, err := sec.Unlock(&managerKey) if err != nil { return nil, fmt.Errorf("room security unlock error: %s", err) } managerCaps := make([]*security.PublicKeyCapability, len(managers)) for i, manager := range managers { kp := manager.KeyPair() c, err := security.GrantPublicKeyCapability( kms, sec.Nonce, roomKeyPair, &kp, nil, managerKey.Plaintext) if err != nil { return nil, fmt.Errorf("manager grant error: %s", err) } managerCaps[i] = c } accessCaps := []*security.PublicKeyCapability{} if private { accessCaps = make([]*security.PublicKeyCapability, len(managers)) for i, manager := range managers { kp := manager.KeyPair() c, err := security.GrantPublicKeyCapability( kms, rmkb.Nonce(), roomKeyPair, &kp, nil, msgKey.Plaintext) if err != nil { return nil, fmt.Errorf("access grant error: %s", err) } accessCaps[i] = c } } // Insert data. t, err := b.DbMap.Begin() if err != nil { return nil, err } rollback := func() { if err := t.Rollback(); err != nil { logging.Logger(ctx).Printf("rollback error: %s", err) } } if err := t.Insert(room); err != nil { logging.Logger(ctx).Printf("room creation error on %s: %s", name, err) rollback() return nil, err } if rmkb != nil { if err := t.Insert(&rmkb.MessageKey, &rmkb.RoomMessageKey); err != nil { logging.Logger(ctx).Printf("room creation error on %s (message key): %s", name, err) rollback() return nil, err } } managerCapTable := RoomManagerCapabilities{ Room: room, Executor: t, } for i, capability := range managerCaps { if err := managerCapTable.Save(ctx, managers[i], capability); err != nil { logging.Logger(ctx).Printf( "room creation error on %s (manager %s): %s", name, managers[i].ID().String(), err) rollback() return nil, err } } messageCapTable := RoomMessageCapabilities{ Room: room, Executor: t, } for i, capability := range accessCaps { if err := messageCapTable.Save(ctx, managers[i], capability); err != nil { logging.Logger(ctx).Printf( "room creation error on %s (access capability): %s", name, err) rollback() return nil, err } } if err := t.Commit(); err != nil { logging.Logger(ctx).Printf("room creation error on %s (commit): %s", name, err) return nil, err } return room.Bind(b), nil }